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

CreateMLで機械学習したモデルを利用して、MS画像の連邦、ジオン軍判定

Posted on 11月 6, 2018 by Takaaki Naganoya

「戦場の絆」のホームページからダウンロードしたMSの画像を学習させた機械学習モデルを使用して、指定のMS画像が地球連邦軍(EFSF)かジオン軍(zeon)かを判定するAppleScriptです。


■©創通・サンライズ 学習時に299×299ピクセルに縮小されるので、モノアイとかそういう部分が特徴量として検出されることはないもよう

両軍合わせて180機体ほどの画像を学習させただけなので、正直なところ判定間違いが多いですが、増やしていくとけっこう簡単に判定できそうです(数万ファイルぐらい画像を学習させるともっと明確な傾向が出てくるかも?)。


▲学習させたMS画像データ。efsf、efsf_stole(鹵獲機体)、zeon、zeon_stole(鹵獲機体)に分けてみた。CoreMLで任意のMS画像がこれらのどのグループに所属する可能性が最も高いかをフォルダ名で返してくることになる

macOS 10.14上のスクリプトエディタは野良Frameworkを認識してくれないので、macOS 10.14.x+Script Debugger上で実行する必要があります。あと、AppleScriptアプレットに書き出して実行すると野良Frameworkを認識して実行するので、アプレットに書き出して実行するとScript DebuggerのないmacOS 10.14環境でも動作確認できます。

Xcode上でSwift Playgroundを用いて認識していた時よりも認識精度が下がっているように見えます。結局画像は299×299ピクセルぐらいに縮小されて判定されるので、判定前に画像余白部分をトリミングしておくと認識精度が上がりそうな気もします。

299×299ピクセルに縮小されると、さすがにモノアイが特徴量として認識される可能性も低く、色とかポーズとか構図とかで識別されているのでしょう。


▲作成したmodelをNetronでビジュアライズしたところ

CreateMLで機械学習モデルを作るのがとても簡単であることがわかり、機械学習モデルを呼び出すためのAppleScriptのコードがとてもシンプルなことがわかり、さらに学習モデルを用いた画像分類が短い時間で行えることを確認できました。

現在のところ、1つの機械学習モデル(.mlmodel)を使うためにそのモデルを組み込んだFrameworkを必要としている状態ですが、機械学習モデル自体も外部からパスで指定して柔軟に指定できるようにしたいところです。

これで調子に乗って手書き文字画像データ(Mnist)をCreateMLで機械学習して、手書き文字の画像をスキャナから読み取って手軽に手書き文字認識できるかも?! と、鼻息荒くテストしてみましたが、期待したような精度では判定されないことを思い知らされたのでした。

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

AppleScript名:機械学習で学習したMSの画像の連邦軍、ジオン軍判定.scpt
use AppleScript version "2.7" — Mojave (10.14) or later
use framework "Foundation"
use framework "AppKit"
use framework "msDetector"
use scripting additions

set aFile to POSIX path of (choose file of type {"public.image"})
set aImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:aFile
set msRes to current application’s msClassify’s alloc()’s init()’s ImageClassifierWithImage:aImage
–> "efsf" / "zeon"

★Click Here to Open This Script 

Posted in file Image Machine Learning | Tagged 10.14savvy NSImage | Leave a comment

Table 1の全セルを選択する v3

Posted on 11月 5, 2018 by Takaaki Naganoya

Numbersで選択中のセルがなければ、最前面の書類の選択中のワークシートのうちのTable 1を全選択するAppleScriptです。

選択部分からデータを取得する処理はよく行いますが、プログラム側から選択部分を作成するというのはやっていなかったので、試行錯誤してみました。

AppleScript名:Table 1の全セルを選択する v3.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2018/11/05
—
–  Copyright © 2018 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

tell application "Numbers"
  tell front document
    tell active sheet
      try
        –選択セルがある場合
        
set theTable to first table whose class of selection range is range
      on error
        –選択セルがない場合はTable 1を全選択
        
set tCount to count every table
        
if tCount = 0 then error "There is no table in active sheet"
        
        
tell table 1
          set selection range to cell range
        end tell
        
      end try
    end tell
  end tell
end tell

★Click Here to Open This Script 

Posted in How To | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy Numbers | Leave a comment

電子書籍2冊のリンク切れの対処データが完成

Posted on 11月 4, 2018 by Takaaki Naganoya

2018年1月末の本Blog消失に伴い、電子書籍「AppleScript最新リファレンス」「AppleScript 10大最新技術」本文中からリンクしていた本Blog上のURLの変更先情報補完、および抜けていた記事のBlogへの補充作業がほぼ終了しました。

抜けた記事の再作成&更新作業は割としんどいものでした(ーー;;; 

2つの電子書籍のサポートページ上にURLの対応表を掲載いたしましたので、ご参照ください。

→ 「AppleScript最新リファレンス」サポートページ

→ 「AppleScript 10大最新技術」サポートページ

Posted in Release | Leave a comment

MIKMIDIでデバイス一覧を取得 v2

Posted on 11月 4, 2018 by Takaaki Naganoya

オープンソースのフレームワーク「MIKMIDI」を用いてMIDIデバイス情報を取得するAppleScriptです。

Objective-Cのプログラムもいろいろ読んできましたが、その中でもこれは難易度が高く、高尚であるために読んでもさっぱりわかりません。

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

AppleScript名:MIKMIDIでデバイス一覧を取得 v2
— Created 2015-11-13 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "MIKMIDI" –https://github.com/mixedinkey-opensource/MIKMIDI

property midiDeviceManager : missing value

set midiDeviceManager to current application’s MIKMIDIDeviceManager’s sharedDeviceManager()’s availableDevices()
set aRes to midiDeviceManager’s mutableCopy()

set endpointsInDevs to current application’s NSMutableSet’s |set|()
repeat with i in (midiDeviceManager as list)
  set aSrcList to (current application’s NSSet’s setWithArray:(i’s entities()’s valueForKeyPath:"sources"))
  
set aDstList to (current application’s NSSet’s setWithArray:(i’s entities()’s valueForKeyPath:"destinations"))
  (
endpointsInDevs’s unionSet:aSrcList)
  (
endpointsInDevs’s unionSet:aDstList)
end repeat

endpointsInDevs’s |description|()
–>  (NSSet) {{(MIKMIDISourceEndpoint) <MIKMIDISourceEndpoint: 0x7f8a61d47950> 新しい外部装置}, {(MIKMIDISourceEndpoint) <MIKMIDISourceEndpoint: 0x7f8a63a65610> IAC Driver GarageBand}, {(MIKMIDIDestinationEndpoint) <MIKMIDIDestinationEndpoint: 0x7f8a61bbc130> IAC Driver GarageBand}, {(MIKMIDIDestinationEndpoint) <MIKMIDIDestinationEndpoint: 0x7f8a5ecadcf0> 新しい外部装置}}

–midiDeviceManager’s virtualSources() –Real MIDI I/Fがつながっていないとエラーになる
–set devicelessSources to current application’s NSMutableSet’s setWithWrray:(midiDeviceManager’s virtualSources())

★Click Here to Open This Script 

Posted in MIDI System | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

指定URLをロード_WKWebView版 v2

Posted on 11月 4, 2018 by Takaaki Naganoya

指定のURLを読み込んでページのタイトルを取得するAppleScriptです。

オリジナルはControl+Command+Rの操作が必要でしたが、本バージョンでは必要ありません。ただ、Script Debuggerとの相性はよろしくないようで。

AppleScript名:指定URLをロード_WKWebView版 v2
— Created 2015-09-16 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "WebKit"

property theWebView : missing value

set aURL to "http://www.apple.com/jp/shop/browse/home/specialdeals/mac"

my performSelectorOnMainThread:"getPage:" withObject:(aURL) waitUntilDone:true

set aTitle to (theWebView)’s title()
return aTitle as text
–>  "Mac整備済製品 – Apple(日本)"

–Download the URL page to WkWebView
on getPage:aURL
  set thisURL to current application’s |NSURL|’s URLWithString:aURL
  
set theRequest to current application’s NSURLRequest’s requestWithURL:thisURL
  
  
set aConf to current application’s WKWebViewConfiguration’s alloc()’s init()
  
  
set (my theWebView) to current application’s WKWebView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 800, 600)) configuration:aConf –フレームの大きさは根拠レス
  (
my theWebView)’s setNavigationDelegate:me
  (
my theWebView)’s loadRequest:theRequest
  
  
set waitLoop to 100 * 60 –60 seconds
  
  
set hitF to false
  
repeat waitLoop times
    set aLoadF to ((my theWebView)’s estimatedProgress()) as number
    
if aLoadF = 1.0 then
      set hitF to true
      
exit repeat
    end if
    
current application’s NSThread’s sleepForTimeInterval:(0.01)
    
–delay 0.1
  end repeat
  
  
return hitF
end getPage:

★Click Here to Open This Script 

Posted in URL | Tagged 10.11savvy 10.12savvy 10.13savvy NSThread NSURL NSURLRequest WKWebView WKWebViewConfiguration | Leave a comment

QuartzComoserでグラフ表示てすと v6

Posted on 11月 4, 2018 by Takaaki Naganoya

QuartzComposerのグラフに任意のデータを指定してウィンドウ表示するAppleScriptです。

スクリプトバンドル内の「Chart.qtz」を読み出して表示しているため、QuartzComposer入りのスクリプトバンドルを用意しておきましたので、ダウンロードしてお試しください。

–> Download qtc_disp_v6

オリジナルはControl+Command+Rで実行する必要がありましたが、本Scriptではその必要がありません。ちなみに、一般的なQuartzComposerのようにマウスでグリグリ回せるとかいうことはありません。パラメータを反映して静止画として表示されるだけです(Xcode上で作成したAppleScriptのGUIアプリケーションであれば、普通に回せます)。

macOS 10.14上で実行してみたところ、スクリプトエディタではCompositionが表示されませんでしたが、Script Debugger上で実行したかぎりでは実行されました。Framework宣言で足りないものがあるのでしょうか?

備考:QuartzComposerはmacOS 10.15でDeprecated扱いになりました

AppleScript名:QuartzComoserでグラフ表示てすと v6
— Created 2015-11-03 by Takaaki Naganoya
— Modified 2018-11-04 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Quartz"
use framework "AppKit"

property NSColor : a reference to current application’s NSColor
property QCView : a reference to current application’s QCView
property NSString : a reference to current application’s NSString
property NSScreen : a reference to current application’s NSScreen
property NSWindow : a reference to current application’s NSWindow
property NSNumber : a reference to current application’s NSNumber
property NSPredicate : a reference to current application’s NSPredicate
property NSDictionary : a reference to current application’s NSDictionary
property NSMutableArray : a reference to current application’s NSMutableArray
property NSWindowController : a reference to current application’s NSWindowController
property NSMutableDictionary : a reference to current application’s NSMutableDictionary
property NSTitledWindowMask : a reference to current application’s NSTitledWindowMask
property NSWindowCloseButton : a reference to current application’s NSWindowCloseButton
property NSNormalWindowLevel : a reference to current application’s NSNormalWindowLevel
property NSBackingStoreBuffered : a reference to current application’s NSBackingStoreBuffered

set chartData to NSMutableArray’s new()
chartData’s addObject:(my recWithLabels:{"label", "value"} andValues:{"練馬区", 3})
chartData’s addObject:(my recWithLabels:{"label", "value"} andValues:{"青梅市", 1})
chartData’s addObject:(my recWithLabels:{"label", "value"} andValues:{"中野区", 2})

my performSelectorOnMainThread:"dispQuartzComposerWindow:" withObject:(chartData) waitUntilDone:true

on dispQuartzComposerWindow:chartData
  –上記データの最大値を求める
  
set aMaxRec to chartData’s filteredArrayUsingPredicate:(NSPredicate’s predicateWithFormat_("SELF.value == %@.@max.value", chartData))
  
set aMax to value of aMaxRec
  
set aMaxVal to (first item of aMax) as integer
  
  
–Scalingの最大値を求める
  
if aMaxVal ≥ 10 then
    set aScaleMax to (10 div aMaxVal)
    
set aScaleMin to aScaleMax div 10
  else
    set aScaleMax to (10 / aMaxVal)
    
set aScaleMin to 1
  end if
  
  
try
    set aPath to path to resource "Chart.qtz"
  on error
    return
  end try
  
  
set qtPath to NSString’s stringWithString:(POSIX path of aPath)
  
  
set aView to QCView’s alloc()’s init()
  
set qtRes to (aView’s loadCompositionFromFile:qtPath)
  
  
aView’s setValue:chartData forInputKey:"Data"
  
aView’s setValue:(NSNumber’s numberWithFloat:(0.5)) forInputKey:"Scale"
  
aView’s setValue:(NSNumber’s numberWithFloat:(0.2)) forInputKey:"Spacing"
  
aView’s setAutostartsRendering:true
  
  
set maXFrameRate to aView’s maxRenderingFrameRate()
  
  (
aView’s setValue:(NSNumber’s numberWithFloat:aScaleMax / 10) forInputKey:"Scale")
  
  
set aWin to (my makeWinWithView(aView, 800, 600, "AppleScript Composition Test"))
  
  
set wController to NSWindowController’s alloc()
  
wController’s initWithWindow:aWin
  
aWin’s makeFirstResponder:aView
  
wController’s showWindow:me
  
  
aWin’s makeKeyAndOrderFront:me
  
  
delay 5
  
  
my closeWin:aWin
  
aView’s stopRendering() –レンダリング停止
  
end dispQuartzComposerWindow:

–make Window for Display
on makeWinWithView(aView, aWinWidth, aWinHeight, aTitle)
  set aScreen to NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
  
  
set aBacking to NSTitledWindowMask
  
  
set aDefer to NSBackingStoreBuffered
  
  
— Window
  
set aWin to NSWindow’s alloc()
  (
aWin’s initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
  
aWin’s setBackgroundColor:(NSColor’s whiteColor())
  
  
aWin’s setTitle:aTitle
  
aWin’s setDelegate:me
  
aWin’s setDisplaysWhenScreenProfileChanges:true
  
aWin’s setHasShadow:true
  
aWin’s setIgnoresMouseEvents:false
  
aWin’s setLevel:(NSNormalWindowLevel)
  
aWin’s setOpaque:false
  
aWin’s setReleasedWhenClosed:true
  
aWin’s |center|()
  
aWin’s makeKeyAndOrderFront:(me)
  
–aWin’s movableByWindowBackground:true
  
  
— Set Custom View
  
aWin’s setContentView:aView
  
  
–Set Close Button  
  
set closeButton to NSWindow’s standardWindowButton:(NSWindowCloseButton) forStyleMask:(NSTitledWindowMask)
  
  
return aWin
end makeWinWithView

–close win
on closeWin:aWindow
  repeat with n from 10 to 1 by -1
    (aWindow’s setAlphaValue:n / 10)
    
delay 0.01
  end repeat
  
aWindow’s |close|()
end closeWin:

on recWithLabels:theKeys andValues:theValues
  return (NSDictionary’s dictionaryWithObjects:theValues forKeys:theKeys) as record
end recWithLabels:andValues:

★Click Here to Open This Script 

Posted in GUI Image | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy NSColor NSDictionary NSMutableArray NSMutableDictionary NSNumber NSPredicate NSScreen NSString NSWindow NSWindowController QCView | Leave a comment

テキストをMarkdown形式として解釈してHTMLを出力

Posted on 11月 3, 2018 by Takaaki Naganoya

オープンソースのフレームワーク「MMMarkdown」を利用してMarkdownのテキストをHTMLに変換して出力するAppleScriptです。

ただし、解釈できるMarkdownタグは限定的で、表などは解釈できません。

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

AppleScript名:テキストをMarkdown形式と解釈してHTMLを出力
— Created 2016-05-12 by Takaaki Naganoya
— 2016 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "MMMarkdown" –https://github.com/mdiep/MMMarkdown

set markdown to "# Example
What a library!"

set htmlString to (current application’s MMMarkdown’s HTMLStringWithMarkdown:markdown |error|:(missing value)) as string
–>
(*
"<h1>Example</h1>
<p>What a library!</p>
"
*)

★Click Here to Open This Script 

Posted in Markdown Text | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

ftpKitのじっけん ftpサーバーからファイル一覧を取得

Posted on 11月 3, 2018 by Takaaki Naganoya

オープンソースのFTPManagerをフレームワーク化したftpKitを利用して、指定サーバー上の指定ディレクトリ内のファイル一覧を取得するAppleScriptです。

sftp接続が必要な場合にはTransmitをAppleScriptからコントロールすることになるわけですが、セキュリティ的にあまり問題にならない用途であればFTP経由でファイル転送することもあるでしょう。

AppleScript名:ftpKitでファイル一覧を取得
— Created 2016-03-01by Takaaki Naganoya
— 2016 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "ftpKit" –https://github.com/nkreipke/FTPManager

set serverURL to "ftp://www.piyocast.com/xxxxx/public_html/private"
set serverUser to "xxxxx@piyocast.com"
set serverPassword to text returned of (display dialog "Input FTP Password" default answer "" with hidden answer)

set aFtpManager to current application’s FTPManager’s alloc()’s init()
set successF to false

set srv to current application’s FMServer’s serverWithDestination:serverURL username:serverUser |password|:serverPassword
srv’s setPort:21

set aResList to aFtpManager’s contentsOfServer:srv

set fileNameList to {}
set fileCount to aResList’s |count|()

repeat with i from 0 to (fileCount – 1)
  set anItem to (aResList’s objectAtIndex:i)
  
  
set aFileName to (anItem’s valueForKeyPath:"kCFFTPResourceName") as string
  
set the end of fileNameList to aFileName
end repeat

fileNameList
–>  {".", "..", "xls1a.png", "xls3.png"}

★Click Here to Open This Script 

Posted in file Network | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

度量衡の変換

Posted on 11月 3, 2018 by Takaaki Naganoya

オープンソースの「DDUnitConverter」(By Dave DeLong)を用いて、度量衡(measurement unit)の変換を行うAppleScriptです。AppleScriptから呼び出すために、DDUnitConverterをフレームワーク化した「ddUnitConversionKit」を作成しています。

もともと、AppleScriptには内蔵の度量衡変換機能があり、

AppleScript名:インチからセンチへの変換
set a to 1
set a to a as inches
–> inches 1.0

set b to a as centimeters
–> centimeters 2.54

set c to a as meters
–> meters 0.0254

set d to a as kilometers
–> kilometers 2.54E-5

★Click Here to Open This Script 

とか、

AppleScript名:液体の容積の単位変換
–液体の容積の単位変換
set a to 10 as liters
–> liters 10.0

set b to a as gallons
–> gallons 2.641720372842

set c to a as quarts
–> quarts 10.566881491367

★Click Here to Open This Script 

ぐらいは簡単にできます。AppleScriptがサポートしている度量衡は、長さ、重さ、温度、液体の容積です。

ただ、mmの下のμmとか、オングストロームとか、そういう単位には対応していませんし、重量でいえばKgに対応していてもt(トン)の単位はサポートしていなかったりと、日常的な度量衡の単位の世界でも不十分な感じが否めません(数値の有効桁数が10桁と小さいことも影響?)。

Cocoaの世界で度量衡変換機能について調べてみたところ、km→m→cm→mmといった変換はしてくれるものの、他の単位への変換は行ってくれていなかったりして、標準機能だけではいまひとつな印象です。

AppleScript名:NSLengthFormatterのじっけん
— Created 2015-11-18 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
–http://dev.classmethod.jp/references/ios8-new-formatter/

set aLengthFormatter to current application’s NSLengthFormatter’s alloc()’s init()
set aMeters to 5000
set aRes to (aLengthFormatter’s stringFromMeters:aMeters) as text
–>  "5 km"
set bRes to (aLengthFormatter’s stringFromMeters:500) as text
–>  "500 m"
set cRes to (aLengthFormatter’s stringFromMeters:0.5) as text
–>  "50 cm"
set dRes to (aLengthFormatter’s stringFromMeters:0.005) as text
–>  "5 mm"
set eRes to (aLengthFormatter’s stringFromMeters:("0.000005" as real)) as text
–>  "0.005 mm"

set res2 to aLengthFormatter’s getObjectValue:(missing value) forString:aRes errorDescription:(missing value)
–>  false

set res3 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitMillimeter)) as text
–>  "5,000 mm"
set res4 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitCentimeter)) as text
–>  "5,000 cm"
set res5 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitMeter)) as text
–>  "5,000 m"
set res6 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitKilometer)) as text
–>  "5,000 km"
set res7 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitInch)) as text
–>  "5,000 in"
set res8 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitFoot)) as text
–>  "5,000 ft"
set res9 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitYard)) as text
–>  "5,000 yd"
set res10 to (aLengthFormatter’s stringFromValue:aMeters unit:(current application’s NSLengthFormatterUnitMile)) as text
–>  "5,000 mi"

★Click Here to Open This Script 

AppleScript名:NSMassFormatterのじっけん
— Created 2015-11-18 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
–http://dev.classmethod.jp/references/ios8-new-formatter/

set aMasFormatter to current application’s NSMassFormatter’s alloc()’s init()
set aKilloGrams to 60.0
set aRes to (aMasFormatter’s stringFromKilograms:aKilloGrams) as text
–>  "60 kg"
set a2Res to (aMasFormatter’s stringFromKilograms:(0.5)) as text
–>  "500 g"
set a3Res to (aMasFormatter’s stringFromKilograms:(5000000)) as text
–>  "5,000,000 kg"
set a4Res to (aMasFormatter’s stringFromKilograms:("0.0005" as real)) as text
–>  "0.5 g"

set bRes to (aMasFormatter’s stringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitGram)) as text
–>  "60 g"
set cRes to (aMasFormatter’s stringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitKilogram)) as text
–>  "60 kg"
set dRes to (aMasFormatter’s stringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitOunce)) as text
–>  "60 oz"
set eRes to (aMasFormatter’s stringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitPound)) as text
–>  "60 lb"
set fRes to (aMasFormatter’s stringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitStone)) as text
–>  "60 st"

set gRes to (aMasFormatter’s unitStringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitGram)) as text
–>  "g"
set hRes to (aMasFormatter’s unitStringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitKilogram)) as text
–>  "kg"
set iRes to (aMasFormatter’s unitStringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitOunce)) as text
–>  "oz"
set jRes to (aMasFormatter’s unitStringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitPound)) as text
–>  "lb"
set kRes to (aMasFormatter’s unitStringFromValue:aKilloGrams unit:(current application’s NSMassFormatterUnitStone)) as text
–>  "st"

set res01 to aMasFormatter’s getObjectValue:(missing value) forString:fRes errorDescription:(missing value)
–>  false

set res02 to (aMasFormatter’s stringFromKilograms:80) as text
–>  "80 kg"

set res03 to aMasFormatter’s unitStyle()
–>  2 = NSFormattingUnitStyleMedium

★Click Here to Open This Script 

そこで、冒頭に紹介したようにDDUnitConverterを導入してみたわけですが、これはこれで問題がないわけでもありません。本来、通貨同士の変換をサポートしており、通貨レートの更新機能を持っているのですが、実際に呼び出してみると更新されていない雰囲気が濃厚です(呼び出し方を間違っているのか?)。

なので、「通貨レート以外」の度量衡変換にのみ用いるのが安全な使い方なのかもしれない、というところです。

例によって、OS X 10.10以降用にビルドしたバイナリを用意しておきましたので、興味のある方はアーカイブを展開したあとで、~/Library/Frameworksに入れておためしください。

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

AppleScript名:DDUnitConverterのじっけん1
— Created 2015-11-19 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version “2.4”
use scripting additions
use framework “Foundation”
use framework “ddUnitConversionKit” –davedelong/DDUnitConverter
–https://github.com/davedelong/DDUnitConverter

–enums in DDVelocityUnitConverter.h
property DDVelocityUnitCentimetersPerHour : 0
property DDVelocityUnitCentimetersPerMinute : 1
property DDVelocityUnitCentimetersPerSecond : 2
property DDVelocityUnitFeetPerHour : 3
property DDVelocityUnitFeetPerMinute : 4
property DDVelocityUnitFeetPerSecond : 5
property DDVelocityUnitInchesPerHour : 6
property DDVelocityUnitInchesPerMinute : 7
property DDVelocityUnitInchesPerSecond : 8
property DDVelocityUnitKilometersPerHour : 9
property DDVelocityUnitKilometersPerMinute : 10
property DDVelocityUnitKilometersPerSecond : 11
property DDVelocityUnitKnots : 12
property DDVelocityUnitLight : 13
property DDVelocityUnitMach : 14
property DDVelocityUnitMetersPerHour : 15
property DDVelocityUnitMetersPerMinute : 16
property DDVelocityUnitMetersPerSecond : 17
property DDVelocityUnitMilesPerHour : 18
property DDVelocityUnitMilesPerMinute : 19
property DDVelocityUnitMilesPerSecond : 20
property DDVelocityUnitFurlongsPerFortnight : 21

–時速100kmを秒速kmに変換
set aVal to ((current application’s DDUnitConverter’s velocityUnitConverter())’s convertNumber:100 fromUnit:(DDVelocityUnitKilometersPerHour) toUnit:(DDVelocityUnitKilometersPerSecond)) as real
–>  0.027777777778

★Click Here to Open This Script 

AppleScript名:DDCurrencyUnitConverterのじっけん
— Created 2015-11-19 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version “2.4”
use scripting additions
use framework “Foundation”
use framework “ddUnitConversionKit” –davedelong/DDUnitConverter
–https://github.com/davedelong/DDUnitConverter

–enums in DDCurrencyUnitConverter.h
property DDCurrencyUnitEuro : 0
property DDCurrencyUnitJapaneseYen : 1
property DDCurrencyUnitUKPoundSterling : 2
property DDCurrencyUnitUSDollar : 3
property DDCurrencyUnitAlgerianDinar : 4
property DDCurrencyUnitArgentinePeso : 5
property DDCurrencyUnitAustralianDollar : 6
property DDCurrencyUnitBahrainDinar : 7
property DDCurrencyUnitBotswanaPula : 8
property DDCurrencyUnitBrazilianReal : 9
property DDCurrencyUnitBruneiDollar : 10
property DDCurrencyUnitCanadianDollar : 11
property DDCurrencyUnitChileanPeso : 12
property DDCurrencyUnitChineseYuan : 13
property DDCurrencyUnitColombianPeso : 14
property DDCurrencyUnitCzechKoruna : 15
property DDCurrencyUnitDanishKrone : 16
property DDCurrencyUnitHungarianForint : 17
property DDCurrencyUnitIcelandicKrona : 18
property DDCurrencyUnitIndianRupee : 19
property DDCurrencyUnitIndonesianRupiah : 20
property DDCurrencyUnitIranianRial : 21
property DDCurrencyUnitIsraeliNewSheqel : 22
property DDCurrencyUnitKazakhstaniTenge : 23
property DDCurrencyUnitKoreanWon : 24
property DDCurrencyUnitKuwaitiDinar : 25
property DDCurrencyUnitLibyanDinar : 26
property DDCurrencyUnitMalaysianRinggit : 27
property DDCurrencyUnitMauritianRupee : 28
property DDCurrencyUnitMexicanPeso : 29
property DDCurrencyUnitNepaleseRupee : 30
property DDCurrencyUnitNewZealandDollar : 31
property DDCurrencyUnitNorwegianKrone : 32
property DDCurrencyUnitRialOmani : 33
property DDCurrencyUnitPakistaniRupee : 34
property DDCurrencyUnitNuevoSol : 35
property DDCurrencyUnitPhilippinePeso : 36
property DDCurrencyUnitPolishZloty : 37
property DDCurrencyUnitQatarRiyal : 38
property DDCurrencyUnitRussianRuble : 39
property DDCurrencyUnitSaudiArabianRiyal : 40
property DDCurrencyUnitSingaporeDollar : 41
property DDCurrencyUnitSouthAfricanRand : 42
property DDCurrencyUnitSriLankaRupee : 43
property DDCurrencyUnitSwedishKrona : 44
property DDCurrencyUnitSwissFranc : 45
property DDCurrencyUnitThaiBaht : 46
property DDCurrencyUnitTrinidadAndTobagoDollar : 47
property DDCurrencyUnitTunisianDinar : 48
property DDCurrencyUnitUAEDirham : 49
property DDCurrencyUnitPesoUruguayo : 50
property DDCurrencyUnitBolivarFuerte : 51
property DDCurrencyUnitSDR : 52

–最初に通貨レートの更新を行う必要があるが、実行しても変わらないのはなぜ????
set aConv to current application’s DDUnitConverter’s currencyUnitConverter()
aConv’s refreshExchangeRates()
set aVal to (aConv’s convertNumber:100 fromUnit:(DDCurrencyUnitUSDollar) toUnit:(DDCurrencyUnitJapaneseYen))
–>  (NSNumber) 1.006839721743

★Click Here to Open This Script 

Posted in Number | Tagged 10.11savvy 10.12savvy 10.13savvy NSLengthFormatter NSMassFormatter | Leave a comment

シリアルコードの生成と検証

Posted on 11月 3, 2018 by Takaaki Naganoya

オープンソースのフレームワーク「SerialKeyGenerator」を用いてシリアルコードを生成、検証するAppleScriptです。

シリアルコードについて

シリアルコードは、日本では「レジストコード」「プロダクトコード」などと呼ばれるもので、ソフトウェアの販売時にこのコードを発行し、ソフトウェアのシリアルコード入力ダイアログに入力してもらうことで、完全版として機能させるというものです。

Mac App StoreではApple IDとひもづけることでシリアルコードを使用しないソフトウェア販売とライセンシングを行なっていますが、Mac App Store外で販売する場合にはシリアルコードのことを考える必要が出てきます。

コードの文字数を増やすと、仮にキーボードから入力する場合の難易度が上がってしまいます。適度な長さの文字列になることが望ましいところです。

シリアルコードが仮に流出した場合に備え、どの購入者のコードが流出したかを特定する必要があります。そのため、シリアルコードにはその名のとおり、購入者の番号を含めてあるのが普通です。

SerialKeyGeneratorの使い方について

SerialKeyGeneratorでは、シークレットキーワード、ユーザー番号をもとにシリアルコードが生成されます。日時を考慮してシリアルコードを計算するため、同じシリアルコードを生成させても日時が変われば結果は異なります。

ただ、おおもとのシークレットキーワードが判明してしまうと、第三者がシリアルコードを勝手に発行してソフトウェアの不正使用ができてしまうため、アプリケーション内に格納するシークレットキーワードは文字ダンプされても判明しないようにしておくのが普通です。

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

AppleScript名:SerialKeyGeneratorサンプル1
— Created 2015-10-24 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "serialKeyGenKit" –https://github.com/danielvy/SerialKeyGenerator

–Generate Serial Code with secret Keyword
set aGen to current application’s SerialKeyGenerator’s alloc()’s initWithSecret:"Piyomaru"
–>  (SerialKeyGenerator) <SerialKeyGenerator: 0x7f8b5b5fa200>

set aList to {}
repeat with i from 1 to 10
  set aRes to (aGen’s generateSerialWithSequence:i |data|:i)
  
set the end of aList to (aRes as text)
end repeat

aList
–>  {​​​​​"1CHH8-BJY89-TR9Z9-AKSTL-70JZF", ​​​​​"4KXCF-LS6P5-7BKYN-CUMPY-NM072", ​​​​​"41GO2-OGZ3T-83YP9-2LS4J-9W3MI", ​​​​​"CA3WV-C7FU7-PSPJ3-LNGT7-N6AJT", ​​​​​"3OG0B-MCFUM-7YKHT-EE533-LNJEJ", ​​​​​"4SKWQ-9G8XE-ZCE6K-APSAL-R0T8S", ​​​​​"CTEZT-H4AQQ-BM15H-FH2DG-P7K7O", ​​​​​"4BZ1X-2OHKF-5FWND-7SZVA-EBR89", ​​​​​"BDKRI-9JU7T-G6N20-YPU9K-6FXQW", ​​​​​"9EWW5-O3FMV-SDEZA-77JZE-OY8FL"​​​}

–Decode Serial with secret Keyword
set rList to {}
set bGen to current application’s SerialKeyGenerator’s alloc()’s initWithSecret:"Piyomaru"
–> (SerialKeyGenerator) <SerialKeyGenerator: 0x7fb6992b8400>

repeat with i in aList
  set bRes to (bGen’s decodeSerial:(contents of i))
  
  
set aDate to bRes’s |date| as date
  
set aSeq to bRes’s sequence as integer
  
set aData to bRes’s |data| as integer
  
  
set the end of rList to {aData, aSeq, aDate}
end repeat
return rList
–> {{1, 1, date "2018年11月3日土曜日 16:44:57"}, {2, 2, date "2018年11月3日土曜日 16:44:57"}, {3, 3, date "2018年11月3日土曜日 16:44:57"}, {4, 4, date "2018年11月3日土曜日 16:44:57"}, {5, 5, date "2018年11月3日土曜日 16:44:57"}, {6, 6, date "2018年11月3日土曜日 16:44:57"}, {7, 7, date "2018年11月3日土曜日 16:44:57"}, {8, 8, date "2018年11月3日土曜日 16:44:57"}, {9, 9, date "2018年11月3日土曜日 16:44:57"}, {10, 10, date "2018年11月3日土曜日 16:44:57"}}

★Click Here to Open This Script 

Posted in How To | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

Excelデータを組み立てて書き出し(フォント指定、カラー指定)

Posted on 11月 3, 2018 by Takaaki Naganoya

オープンソースのフレームワーク「JXLS」を用いてExcelデータを組み立てるAppleScriptです。

フォント名と色を指定してみました。実際に案件で使用したことがないので、徹底的に活用した………という経験がないので、いまのところ何か風景画像をExcel書類に変換して「実はExcelで作りました」とかフカすぐらいしか用途がなさそうです。

–> Download JXLS(To ~/Library/Frameworks/)

AppleScript名:ASOCでExcelファイル生成テスト v2
— Created 2015-10-08 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "JXLS" –https://github.com/JanX2/JXLS

set aFile to POSIX path of (choose file name)
set filePath to current application’s NSString’s stringWithString:aFile

set workBook to current application’s JXLSWorkBook’s new()
set workSheet to workBook’s workSheetWithName:"ぴよぴよシート"
workSheet’s setWidth:1000 forColumn:0 defaultFormat:(missing value)

repeat with i from 0 to 64
  set aCell to (workSheet’s setCellAtRow:i column:0 toString:(current application’s NSString’s stringWithString:("ぴよまる " & (i as text))))
  (
aCell’s setFontName:"HiraKakuStd-W8")
  (
aCell’s setFontHeight:320) –this is point * 20
  (
aCell’s setFontColorIndex:i)
  (
aCell’s setForegroundFillColorIndex:13)
end repeat

workBook’s writeToFile:filePath

★Click Here to Open This Script 

Posted in How To | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

Excelデータを組み立てて書き出し

Posted on 11月 3, 2018 by Takaaki Naganoya

オープンソースの「JXLS.framework」を用いて指定のExcelデータを組み立てて書き出すAppleScriptです。

アプリケーションにメッセージを送ってアプリケーションに仕事をしてもらうのがAppleScriptの流儀ですが、macOS 10.10以降でCocoaの機能が呼べるようになったため、こうしたオープンソースのフレームワークを呼び出して処理できるようになりました。

AppleScriptが自前で行なっていないことには変わらないのですが、Excelデータを(Excelなしで)組み立てられるわけで、出力データとしてExcel書類が求められる用途において、Excelなしで処理が行えます(開発中はExcelでどのように表示されるか確認する必要があるので、開発中は必要です)。

また、本物のExcelをコントロールする方法ではできなかった「並列処理で大量にデータを作成する」という処理も可能になるわけでけっこうなことです(ただ、そういう要求をされたことは皆無なのですが、、、、)。

–> Download JXLS(To ~/Library/Frameworks/)

AppleScript名:ASOCでExcelファイル生成テスト
— Created 2015-10-08 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "JXLS" –https://github.com/JanX2/JXLS

set aFile to POSIX path of (choose file name)
set filePath to current application’s NSString’s stringWithString:aFile

set workBook to current application’s JXLSWorkBook’s new()

set workSheet to workBook’s workSheetWithName:"ぴよぴよシート"
workSheet’s setWidth:1000 forColumn:0 defaultFormat:(missing value)

repeat with i from 0 to 10
  set aCell to (workSheet’s setCellAtRow:i column:0 toString:(current application’s NSString’s stringWithFormat_("ぴよまる %@", i + 1)))
  (
aCell’s setHorizontalAlignment:1) —-HALIGN_LEFT
  (
aCell’s setIndentation:(0 + i)) —– INDENT_0
end repeat

workBook’s writeToFile:filePath

★Click Here to Open This Script 

Posted in Release | Tagged 10.11savvy 10.12savvy 10.13savvy NSString | Leave a comment

ASOCでXML-RPCのテスト v3

Posted on 11月 3, 2018 by Takaaki Naganoya

オープンソースのXMLRPC.frameworkを用いてXMLRPCを実行するAppleScriptです。

XMLRPCといえば、WordPressか郵便専門ネットかというほど用途が限定されていますが、本Blog(Powered By WordPress)の年初の再構築など、使えないと大変な思いをすることがあるので、定期的に調査しています。

初回掲載時は郵便専門ネットのXMLRPCはバージョン番号を”15.09a”と返してきましたが、再掲載時に実行してみたら”18.10a”を返してきました。

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

AppleScript名:ASOCでXML-RPCのテスト v3
— Created 2015-10-06 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "XMLRPC"
–XMLRPC.framework
–https://cocoapods.org/pods/xmlrpc
–Cocoa XML-RPC Framework © 2011 Divisible by Zero
–v2.3.4

set aRes to (callXMLRPC("http://yubin.senmon.net/service/xmlrpc/", "yubin.getMaxFetchCount", missing value)) as integer
–>  100

set bRes to (callXMLRPC("http://yubin.senmon.net/service/xmlrpc/", "yubin.getVersion", missing value)) as text
–> "15.09a"

on callXMLRPC(paramURL, aMethod, aParamList)
  
  
set aURL to current application’s |NSURL|’s URLWithString:paramURL
  
set aReq to current application’s XMLRPCRequest’s alloc()’s initWithURL:aURL
  
aReq’s setMethod:aMethod withParameter:aParamList
  
set aRes to current application’s XMLRPCConnection’s sendSynchronousXMLRPCRequest:aReq |error|:(missing value)
  
  
set errF to (aRes’s isFault()) as boolean
  
  
if errF = true then
    set xmlRPCres to faultCode of aRes
    
–set xmlRPCbody to faultString of aRes
  else
    set xmlRPCres to aRes’s object()
    
–set xmlRPCbody to aRes’s body()
  end if
  
  
return xmlRPCres
  
end callXMLRPC

★Click Here to Open This Script 

Posted in XML-RPC | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

テキストビュー+ボタンを作成 v2

Posted on 11月 3, 2018 by Takaaki Naganoya

Window+TextView+Buttonを作成してボタンのクリックを受け付けるAppleScriptです。

ちょっとしたログ表示などのために作成したものです。


▲通常(ライト)モード@macOS 10.12.6、ダークモード@10.14.1

オリジナルはスクリプトエディタ上でCommand+Control+Rの「フォアグラウンドで実行」を実行する必要があったのですが、

本バージョンでは強制的にメインスレッド実行を行うことで、この操作は不要になっています。

ただ、ランタイム環境ごとに「ボタンをクリックできない」という現象に遭遇。他のいろいろなランタイムでも試しておく必要を感じます。

ランタイム環境 スクリプトエディタ アプレット スクリプトメニュー osascript Script Debugger
macOS 10.12 OK OK クリックできない クリックできない クリックできない
macOS 10.13 OK OK クリックできない クリックできない クリックできない
macOS 10.14 OK OK クリックできない クリックできない クリックできない

macOS 10.12.6、10.13.6、10.14.1で動作確認してみましたが、傾向は同じです。Script Debugger上でクリックを受け付けないのはかなり問題が、、、、

AppleScript名:テキストビュー+ボタンを作成 v2
— Created 2015-12-11 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSColor : a reference to current application’s NSColor
property NSScreen : a reference to current application’s NSScreen
property NSButton : a reference to current application’s NSButton
property NSWindow : a reference to current application’s NSWindow
property NSSplitView : a reference to current application’s NSSplitView
property NSTextView : a reference to current application’s NSTextView
property NSScrollView : a reference to current application’s NSScrollView
property NSMutableString : a reference to current application’s NSMutableString
property NSWindowController : a reference to current application’s NSWindowController
property NSTitledWindowMask : a reference to current application’s NSTitledWindowMask
property NSRoundedBezelStyle : a reference to current application’s NSRoundedBezelStyle
property NSNormalWindowLevel : a reference to current application’s NSNormalWindowLevel
property NSBackingStoreBuffered : a reference to current application’s NSBackingStoreBuffered
property NSMomentaryLightButton : a reference to current application’s NSMomentaryLightButton

property windisp : false
property wController : false

set aWidth to 600
set aHeight to 500

set aTitle to "テキストビューのじっけん/TextView Test"
set outText to "ぴよまるソフトウェア / Piyomaru Software "
set aButtonMSG to "OK"

–表示用テキストの作成
set dispStr to NSMutableString’s alloc()’s init()
repeat with i from 1 to 100
  set bStr to (NSMutableString’s stringWithString:(outText & (i as string) & return))
  
set dispStr to (bStr’s stringByAppendingString:dispStr)
end repeat

set paramObj to {aWidth, aHeight, aTitle, dispStr, aButtonMSG, "10"}
my performSelectorOnMainThread:"dispTextView:" withObject:(paramObj) waitUntilDone:true

on dispTextView:paramObj
  set my windisp to false
  
copy paramObj to {aWidth, aHeight, aTitle, dispStr, aButtonMSG, timeOutSecs}
  
  
set aColor to NSColor’s colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:0.9
  
set (my windisp) to true
  
  
–Text View+Scroll Viewをつくる
  
set aScroll to NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight))
  
set aView to NSTextView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight))
  
aView’s setRichText:true
  
aView’s useAllLigatures:true
  
aView’s setTextColor:(NSColor’s cyanColor()) —
  
aView’s setBackgroundColor:aColor
  
aView’s setEditable:false
  
  
aScroll’s setDocumentView:aView
  
aView’s enclosingScrollView()’s setHasVerticalScroller:true
  
  
  
–Buttonをつくる
  
set bButton to (NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, 40)))
  
–bButton’s setButtonType:( NSMomentaryLightButton)
  
–bButton’s setBezelStyle:( NSRoundedBezelStyle)
  
bButton’s setTitle:aButtonMSG
  
bButton’s setTarget:me
  
bButton’s setAction:("clicked:")
  
bButton’s setKeyEquivalent:(return)
  
  
–SplitViewをつくる
  
set aSplitV to NSSplitView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aHeight, aWidth))
  
aSplitV’s setVertical:false
  
  
aSplitV’s addSubview:aScroll
  
aSplitV’s addSubview:bButton
  
aSplitV’s setNeedsDisplay:true
  
  
set aWin to makeWinWithView(aSplitV, aWidth, aHeight, aTitle, 0.9)
  
aView’s setString:dispStr
  
  
–NSWindowControllerを作ってみた
  
set my wController to NSWindowController’s alloc()
  
my (wController’s initWithWindow:aWin)
  
  
my (wController’s showWindow:me)
  
  
set aCount to (timeOutSecs as string as number) * 10 –timeout seconds * 10
  
repeat aCount times
    if (my windisp) = false then
      exit repeat
    end if
    
delay 0.1
  end repeat
  
  
my closeWin:bButton
end dispTextView:

–Button Clicked Event Handler
on clicked:aSender
  set (my windisp) to false
  
my closeWin:aSender
end clicked:

–make Window for Input
on makeWinWithView(aView, aWinWidth, aWinHeight, aTitle, alphaV)
  set aScreen to NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
  
set aBacking to NSTitledWindowMask –NSBorderlessWindowMask
  
set aDefer to NSBackingStoreBuffered
  
  
— Window
  
set aWin to NSWindow’s alloc()
  (
aWin’s initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
  
  
aWin’s setTitle:aTitle
  
aWin’s setDelegate:me
  
aWin’s setDisplaysWhenScreenProfileChanges:true
  
aWin’s setHasShadow:true
  
aWin’s setIgnoresMouseEvents:false
  
aWin’s setLevel:(NSNormalWindowLevel)
  
aWin’s setOpaque:false
  
aWin’s setAlphaValue:alphaV –append
  
aWin’s setReleasedWhenClosed:true
  
aWin’s |center|()
  
  
— Set Custom View
  
aWin’s setContentView:aView
  
  
return aWin
end makeWinWithView

–close win
on closeWin:aSender
  set tmpWindow to aSender’s |window|()
  
  
repeat with n from 10 to 1 by -1
    (tmpWindow’s setAlphaValue:n / 10)
    
delay 0.02
  end repeat
  
  
my wController’s |close|()
end closeWin:

★Click Here to Open This Script 

Posted in GUI | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy NSButton NSColor NSMutableString NSScreen NSScrollView NSSplitView NSTextView NSWindow NSWindowController | 1 Comment

AppleScript系機能の実装がおかしなGoogle Chrome

Posted on 11月 2, 2018 by Takaaki Naganoya

Google Chromeは自動処理の部品に使ってはいけない

Google ChromeをAppleScriptでコントロールすることは、個人的にはほとんどありません。日常的に利用するのは、自動処理への対応機能を持ち信頼できるアプリケーションが中心です。

必要な機能がなかったり、自動処理と相性がよくなかったりするためです。使用中にGoogle App Storeのダイアログなどが表示されることがあるので、自動処理中にやられると処理が止まってしまいます。これは、自動処理の仕組みを組み立てる上で絶対にあってはならない仕様です。

そのため、Google ChromeをAppleScriptで動かす場合は、途中でGoogle Chrome側の都合で勝手に処理が止まっても腹が立たない程度の、あまり重要ではない処理であるとか、とても短くて簡単な基礎的なマクロ処理に限定されます。

1日中タイマーにのっとって定時に指定のWebサイトに、複数のユーザーIDやパスワードで繰り返しログインを行い、指定のメニューに移動してデータをダウンロードするような処理(実際にAppleScript+Safariで動かしています)にGoogle Chromeを使うのは自殺行為です。

比較的短めの、

「写真.appで選択中の写真をOCRで文字認識して『戦場の絆』のリプレイIDを取得し、リプレイムービー検索ページにリプレイIDを突っ込み、YouTube上のリプレイムービーのURLを取得。YouTube上でリプレイを再生する」

といった程度の処理でも、途中でGoogle App Storeのダイアログが表示されたら、処理が途切れてそれっきり。コマンドを1つ実行するたびにGoogle App Storeのダイアログを閉じたり無効化する処理を入れれば不可能ではないかもしれませんが、無人の環境で放置するのは無理です。

かといって、Safariの仕様が自動処理に向いているかと言われれば、そういうわけでもありません。ファイルのダウンロード検出をSafari側で行えないなど、自動処理専用のWebブラウザがあったらいいのに、と思うところです(Folder ActionやFSEventsと組み合わせて、非同期処理でダウンロード検出を行なっています)。ただ、Google Chromeのような致命的な動作を行わない点で選択肢になることでしょう。

Google Chromeには、表示中のページのHTMLソースを取得するという、基本的かつないと困る機能が実装されていないのも困りものです。

Google Chromeは実装がおかしい

Google Chromeは一応JavaScriptを実行するための「execute」コマンドを備えているので、JavaScriptのコマンド経由でWebコンテンツへのアクセスや、フォームへのアクセスはできるようになっています。

ただし、肝心の「指定URLをオープンする」という部分の実装がまともに行われていません。

Google Chromeで指定URLをオープンするAppleScriptでよく見かける記述例は、

tell application "Google Chrome"
  open location "http://piyocast.com/as/"
end tell

★Click Here to Open This Script 

のようなものですが、そもそもこの「open location」はAppleScriptの標準命令であり、Google Chromeが持っているコマンドではありません。open locationは指定URLのURLスキームに対応しているアプリケーションに処理が委ねられます。tellブロックを外すと、OSでデフォルト指定されているアプリケーションで処理されます。Google Chromeへのtellブロック内で実行しているので、Google ChromeにURLが転送されているだけです。

Google Chromeの機能を使って指定URLをオープンしようとすると、

tell application "Google Chrome"
  set newWin to make new window
  
tell newWin
    tell tab 1
      set URL to "http://piyocast.com/as/"
    end tell
  end tell
end tell

★Click Here to Open This Script 

のようになります。

一番ひどいのは、Google Chromeのopen命令。これ、

open v : Open a document.
  open list of file : The file(s) to be opened.

用語辞書のとおりに書いてもエラーになります。

そのため、ローカルのファイルをオープンさせようとしても、openコマンドは使えません。fileを与えてもaliasを与えても、AppleScript用語辞書の記述のとおりにfileのlistを与えてもエラーになります。

結論としては、ローカルのfileをオープンする際には、file pathをURL形式に変換して、そのURLをopen locationでオープンするか、tabのURL属性をfile URLに書き換えて表示させることになります。

set anAlias to choose file

tell application "Finder"
  set aURL to URL of anAlias
end tell

tell application "Google Chrome"
  open location aURL
end tell

★Click Here to Open This Script 

set anAlias to choose file

tell application "Finder"
  set aURL to URL of anAlias
end tell

tell application "Google Chrome"
  tell window 1
    tell active tab
      set URL to aURL
    end tell
  end tell
end tell

★Click Here to Open This Script 

Finder経由で目的のファイルをGoogle Chromeというアプリケーションを利用してオープンする、という記述もできますが、ここでもそのままapplication “Google Chrome”と書くとエラーになり、「path to application “Google Chrome”」という回避的な記述が必要になってしまうのでありました。

–By @fixdot on Twitter
set anAlias to choose file

tell application "Finder"
  open anAlias using (path to application "Google Chrome")
end tell

★Click Here to Open This Script 

ただ、ここで書いているのは「自動処理を行うユーザー環境では」ということであって、Google Chromeは自動処理にさえ使わなければ、それなりによくできたいいソフトウェアだと思います。

ほかにもいろいろ落とし穴が

とくに、Google Chromeにかぎらず、macOS内には自動処理の妨げとなる設定項目がいくつか存在しています。デフォルトのまま使うといろいろ問題が出るので、真っ先に設定を変更しています。

Mac miniにBluetooth外付けキーボードを接続した状態で、ファンクションキーをメディアキーに指定して運用していると、iTunesから不定期にダイアログ表示されるため、ファンクションキーはあくまでファンクションキーとして設定しないとダメです(MacBook Proなど本体にキーボードが搭載されているモデルはこのかぎりではありません)。

また、同様にMac miniでヘッドレス(画面なし)運用をしている際に、キーボードやマウス/トラックパッドを接続していない状態で警告するように初期設定されていますが、

 「起動時にキーボードが検出されない場合はBluetooth設定アシスタントを開く」
 「起動時にマウスまたはトラックパッドが検出されない場合はBluetooth設定アシスタントを開く」

の2つのチェックボックスをオフにしておく必要があります。

com.google.Chrome

Posted in file URL | Tagged 10.11savvy 10.12savvy 10.13savvy Google Chrome | Leave a comment

Numbersの表の選択範囲をHTML化 v2

Posted on 11月 1, 2018 by Takaaki Naganoya

Numbersの最前面の書類で選択中の表の範囲をHTML化してファイルに書き出すAppleScriptです。

Numbers v5.1+macOS 10.12.6、Numbers v5.2+macOS 10.13.6、Numbers v5.2+macOS 10.14.1で確認しています。

Numbers v5.xでは書類の書き出し(export)形式にPDF、Microsoft Excel、CSV、Numbers 09の4形式を指定できるようになっていますが、HTMLの表(table)に書き出してくれたりはしません。

GUI側(↑)にその機能がありませんし、AppleScript用語辞書(↓)にもそういう機能は見当たりません。

ただ、HTMLの表に書き出すという処理自体はとても初歩的で簡単な内容なので、「なければ作ればいい」ということになるでしょう。

そこで、ありもののルーチンを組み合わせて、選択範囲をHTMLの表(table)として書き出すScriptを書いて、OS標準装備のScript Menuに入れて利用しています。書き出すHTMLの内容は個人の趣味や用途に応じて大きく変わってきますので、そのあたりは自由に書き換えるとよいと思われます。

本Scriptは、電子書籍「AppleScript最新リファレンス」の正誤表(2018/1のBlog消失事件の影響で、書籍内で参照していたURLリンクが切れてしまったことへの対処)を作成するために、すでに存在していたものにほんの少しの修正を加えたものです。

データベースやデータからHTMLを作成するという処理は、自分がAppleScriptを覚えようと思ったきっかけでもあり(当時は、FileMaker Pro Server経由でLAN上でデータを共有して処理)、感慨深いものがあります。

AppleScript名:表の選択範囲をHTML化 v2
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use bPlus : script "BridgePlus"

script spd
  property uniqList : {}
end script

set (uniqList of spd) to {}

–Numbersからデータを取得する
set aList to get2DListFromNumbersSelection() of me
if aList = false then return

set colCount to (length of first item of first item of aList) + 1

set aHeader to "<!DOCTYPE html><html lang=\"ja\" ><head><meta charset=\"utf-8\"><title>First</title><style>table , td, table , tr, th{border:1px solid #333333;padding:1px;}</style></head><body><table >"
set aTable to "<tr><td>%@</td><td> </td><td>%@</td><td>%@</td><td>%@</td></tr>"
set aFooter to "</table></body></html>"

set aHTMLres to retTableHTML(aList, aHeader, aTable, aFooter) of me

set tFile to choose file name with prompt "Select Output File Name and Folder"
set fRes to writeToFileAsUTF8(aHTMLres, tFile, false) of me

on retTableHTML(aList, aHeaderHTML, aTableHTML, aFooterHTML)
  set allHTML to current application’s NSMutableString’s stringWithString:aHeaderHTML
  
  
set aCounter to 1
  
repeat with i in aList
    set j to contents of i
    
    
set aRowHTML to "<tr>"
    
repeat with ii in j
      set jj to contents of ii
      
if jj = missing value then
        set jj to " "
      else
        try
          set aURL to (current application’s |NSURL|’s URLWithString:jj)
          
if aURL is not equal to missing value then
            set jj to "<a href=\"" & jj & "\">" & jj & "</a>"
          end if
        end try
      end if
      
      
set aTmpHTML to "<td>" & jj & "</td>"
      
set aRowHTML to aRowHTML & aTmpHTML
    end repeat
    
set aRowHTML to aRowHTML & "</tr>"
    
    (
allHTML’s appendString:aRowHTML)
    
set aCounter to aCounter + 1
  end repeat
  
  (
allHTML’s appendString:aFooterHTML)
  
  
return allHTML as list of string or string
end retTableHTML

–テキストを指定デリミタでリスト化
on parseByDelim(aData, aDelim)
  set aText to current application’s NSString’s stringWithString:aData
  
set aList to aText’s componentsSeparatedByString:aDelim
  
return aList as list
end parseByDelim

on get2DListFromNumbersSelection()
  –Numbersで選択範囲を縦に区切ったリストを返す
  
tell application "Numbers"
    tell front document
      tell active sheet
        set theTable to first table whose class of selection range is range
        
        
tell theTable
          try
            set selList to value of every cell of selection range –選択範囲のデータを取得
          on error
            return "" –何も選択されてなかった場合
          end try
          
          
set selName to name of selection range –選択範囲のrange情報を取得
          
set {s1, s2} to parseByDelim(selName, ":") of me
          
          
–始点の情報を取得する
          
set s1Row to (address of row of range s1) as integer
          
set s1Column to (address of column of range s1) as integer
          
          
–終点の情報を取得する
          
set s2Row to (address of row of range s2) as integer
          
set s2Column to (address of column of range s2) as integer
          
          
–選択範囲の情報を取得する
          
set selHeight to s2Row – s1Row + 1 –高さ(Height of selection range)
          
set selWidth to s2Column – s1Column + 1 –幅(Width of selection range)
          
        end tell
      end tell
    end tell
  end tell
  
  
set aLen to length of selList
  
set aaLen to selHeight
  
  
set bList to {}
  
repeat with i from 1 to aaLen
    set aHoriList to {}
    
    
repeat with ii from 1 to selWidth
      set j1 to ii + (i – 1) * selWidth
      
set tmpCon to contents of item j1 of selList
      
      
set aClass to class of tmpCon
      
if aClass = number or aClass = integer or aClass = real then
        set tmpCon to tmpCon as integer
      end if
      
      
set the end of aHoriList to tmpCon
    end repeat
    
    
set the end of bList to aHoriList
  end repeat
  
  
return bList
  
end get2DListFromNumbersSelection

on writeToFileAsUTF8(this_data, target_file, append_data)
  tell current application
    try
      set the target_file to the target_file as text
      
set the open_target_file to open for access file target_file with write permission
      
if append_data is false then set eof of the open_target_file to 0
      
write this_data as «class utf8» to the open_target_file starting at eof
      
close access the open_target_file
      
return true
    on error error_message
      try
        close access file target_file
      end try
      
return error_message
    end try
  end tell
end writeToFileAsUTF8

★Click Here to Open This Script 

Posted in Internet list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy Numbers | Leave a comment

Photosで選択中の写真が指定場所から50メートル以内の場合には書き出してFineReader OCR Proで処理 v2.1

Posted on 10月 30, 2018 by Takaaki Naganoya

Photos(写真).app上で選択中の写真が、指定場所から50メートル以内の場合にはファイルに書き出して、OCRアプリケーション「FineReader OCR Pro」でOCR処理するAppleScriptです。

–> Demo Movie

アーケードゲーム「戦場の絆」のリプレイムービーは、プレイ後の操作により1日に2プレイ分までYouTubeにアップロードされる仕様になっています。プレイ後、ゲーセンのターミナル上で操作してリプレイムービーにアクセスするためのアクセスコード(リプレイID)が表示されるようになっています。

この、ターミナル上のアクセスコードをiPhoneで写真撮影すると、写真に撮影場所のGPSデータが添付されます。写真.app経由でこのGPSデータを取得し、指定場所(ゲームセンター)から50メートル以内であればターミナルで撮影した写真と判定。

この写真をファイル書き出しして、OCRアプリケーションで認識しやすいようにCocoaの機能を用いて階調反転。一昔前ならPhotoshopで処理していましたが、いまならAppleScriptだけで高速に処理できます。デモムービーは実際の速度なので、その速さを体感していただけると思います。写真.appから選択中の写真を取得して反転するまで一瞬です。

反転した画像をMacのOCRアプリケーション「FineReader OCR Pro」でOCR処理し、YouTubeリプレイ再生用のコードを取得します。

あとは、再生用コードをリプレイムービー検索ページのフォームに入れて、実際のYouTube上のリプレイムービーのURLにアクセス。そのまま再生するなり、ダウンロードして保存しておくことになります。


■©創通・サンライズ

本サンプルでは、AppleScriptからコントロール可能なOCRアプリケーション「FineReader OCR Pro」を用いましたが、日本語の文字列を認識しないのであれば、Web APIのOCRサービス(MicrosoftのCognitive Serviceとか)を用いてみてもよいでしょう。

あとは、全国の「戦場の絆」が導入されているゲームセンターの住所情報および緯度経度情報がストックしてあるので、それらのGPSデータと写真撮影地点とのマッチングを行なってみてもよいかもしれません(700箇所程度なので、たいした演算ではありません)。

AppleScript名:Photosで選択中の写真が指定場所から50メートル以内の場合には書き出してFineReader OCR Proで処理 v2.1
— Created 2015-12-04 by Takaaki Naganoya –v2.1
— getDistanceBetweenTwoPlaces : Created 2015-03-03 by Shane Stanley
— convAsFilteredJPEG : Created 2013-12-29 by badcharan@Twitter
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "CoreLocation"
use framework "QuartzCore"

property CIFilter : a reference to current application’s CIFilter
property NSUUID : a reference to current application’s NSUUID
property CIImage : a reference to current application’s CIImage
property NSString : a reference to current application’s NSString
property NSScanner : a reference to current application’s NSScanner
property CLLocation : a reference to current application’s CLLocation
property NSFileManager : a reference to current application’s NSFileManager
property NSCharacterSet : a reference to current application’s NSCharacterSet
property NSJPEGFileType : a reference to current application’s NSJPEGFileType
property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep
property NSMutableCharacterSet : a reference to current application’s NSMutableCharacterSet
property NSRegularExpressionSearch : a reference to current application’s NSRegularExpressionSearch

set targPlace to {35.745769, 139.675565} –Game City Itabashi
set bLoc to getSelectionOnPhotos() of me –Get Location From Photo
set aDist to getDistanceBetweenTwoPlaces(targPlace, bLoc) of me

–指定地点から50メートル以内の距離で撮影された写真であれば、Exportして後続の処理を行う
if aDist is equal to false or aDist > 50 then return false

–選択中の写真のうち最初のものだけExport
set targPhotoAlias to exportSelectedPhotoOnPhotos() of me

–実験に用いた写真はそのままではOCR処理できなかったので、手っ取り早く階調反転を行う
set invertRes to convAsFilteredJPEG(targPhotoAlias, "CIColorInvert") of me
if invertRes = false then
  display dialog "Error in CIImage" with title "Error" buttons {"OK"} default button 1 with icon 2
  
return
end if
set invImage to (POSIX file invertRes) as alias

set outFileName to (NSUUID’s UUID()’s UUIDString() as text) & ".txt"
set outPath to ((path to desktop) as text) & outFileName –sandbox環境ではパスは無視される

tell application id "com.abbyy.FineReaderPro"
  activate
  
  
–Check Ready
  
set getReady to (is finereader controller active)
  
if getReady = false then return
  
  
–set idList to {English} –英語だとスペルチェックされて、"1"と"t"を誤認識するため英語の指定をやめた
  
–Caution: this command is executed asynchronously
  
–Caution: export command was changed in v12.1.4
  
  
set idList to {Basic, Java, Fortran, Cobol, Pascal} –認識ターゲット言語(C++の予約語はあるようだが、指定できないよ!)
  
open invImage — In this version ,we have to open image, at first.
  
export to txt outPath ocr languages enum idList retain layout (as plain text) encoding (utf8)
  
  
–Wait for finish
  
repeat 30 times
    set curStat to (is busy)
    
if curStat = false then exit repeat
    
delay 1
  end repeat
  
  
–sandbox環境(Mac App Store版)の場合にはファイル出力先を別途取得
  
set sandRes to (is sandboxed)
  
if sandRes = true then
    set outDir to (get output dir) as text
    
set outPath to (outDir & outFileName) as text
  end if
  
end tell

–OCR処理した結果のテキストを読み込む
tell current application
  set textRes to read file outPath
end tell

–数字ではじまる行のみを抽出して、リプレイIDを取得
set textList to paragraphs of textRes
set outList to {}
repeat with i in textList
  set j to contents of i
  
  
–1行あたりのテキストが8文字以上か?
  
if length of j > 8 then
    
    
–行頭の文字が数字か?
    
set firstChar to first character of j
    
set nRes to chkNumeric(firstChar) of me
    
if nRes = true then
      set tmp1 to text 2 thru -1 of j –最初の数字を除去
      
      
–数字とアルファベット以外の文字を削除(タブ、スペースなど)
      
set tmp2 to returnNumberAndAlphabetCharsOnly(tmp1) of me
      
if length of tmp2 ≥ 8 then
        set tmp3 to text 1 thru 8 of tmp2
        
–数字とアルファベットの混在の文字列であれば出力する
        
set tmp3Res to chkMixtureOfNumericAndAlphabet(tmp3) of me
        
if tmp3Res = true then
          set the end of outList to tmp3
        end if
      end if
    end if
  end if
end repeat

outList
–> {"4f73vg1v", "v3v32zt3", "yk1z371x", "52yzvn11", "k1ftfvvg"}–Version 1.x (3rd ID is wrong)
–> {"4f73vg1v", "v3v32zt3", "yk1z37tx", "52yzvn11", "k1ftfvvg"}– Version 2.0(Perfect!!!!)
–> {"4f73vg1v", "v3v32zt3", "yk1z37tx", "52yzvn11", "k1ftfvvg"}– Version 2.1(Perfect!!!!)
–> {"51n4gg1f", "2zxt41gg", "57k2txk9", "yy43f3gt", "4f73vg1v"} –Version 2.1(Perfect!!!!)

–Photosで選択中の写真の1枚目(複数時には無視)から緯度、経度情報を取得する
on getSelectionOnPhotos()
  tell application "Photos"
    set aa to selection
    
if aa = {} or aa = missing value then return false
    
set a to first item of aa
    
set aProp to properties of a
    
    
set aLoc to location of aProp
    
return aLoc
  end tell
end getSelectionOnPhotos

–2点間の距離を計算する
on getDistanceBetweenTwoPlaces(aPlaceLoc, bPlaceLoc)
  try
    set {aLat, aLong} to aPlaceLoc
    
set {bLat, bLong} to bPlaceLoc
  on error
    return false
  end try
  
  
set aPlace to CLLocation’s alloc()’s initWithLatitude:aLat longitude:aLong
  
set bPlace to CLLocation’s alloc()’s initWithLatitude:bLat longitude:bLong
  
set distanceInMetres to aPlace’s distanceFromLocation:bPlace
  
return (distanceInMetres as real)
end getDistanceBetweenTwoPlaces

–Photos上で選択中の写真をTemporary Folderに掘ったフォルダに書き出して、そのalias情報を返す
on exportSelectedPhotoOnPhotos()
  set dtPath to (path to temporary items) as text
  
set aUUID to NSUUID’s UUID()’s UUIDString() as text
  
  
set dirPath to ((POSIX path of dtPath) & aUUID)
  
set fileManager to NSFileManager’s defaultManager()
  
set aRes to (fileManager’s createDirectoryAtPath:dirPath withIntermediateDirectories:true attributes:(missing value) |error|:(reference))
  
set dtPath to dtPath & aUUID
  
  
tell application "Photos"
    set a to selection
    
if a = {} then return
    
set aRes to (export a to file dtPath)
  end tell
  
  
tell application "Finder"
    tell folder dtPath
      set fList to (every file) as alias list
    end tell
  end tell
  
  
if fList = {} then return false
  
return first item of fList
end exportSelectedPhotoOnPhotos

–CIFilterをかけたJPEG画像を生成
–参照:http://ashplanning.blogspot.jp/ のうちのどこか
on convAsFilteredJPEG(aPath, aFilterName)
  
  
–aliasをURL(input)とPOSIX path(output) に変換
  
set aURL to (current application’s |NSURL|’s fileURLWithPath:(POSIX path of aPath)) –Input
  
set aPOSIX to (POSIX path of aPath) & "_" & aFilterName & ".jpg" –Output
  
  
–CIImageを生成
  
set aCIImage to CIImage’s alloc()’s initWithContentsOfURL:aURL
  
  
— CIFilter をフィルタの名前で生成
  
set aFilter to CIFilter’s filterWithName:aFilterName
  
aFilter’s setDefaults() –各フィルタのパラメータはデフォルト
  
  
–Filterを実行
  
aFilter’s setValue:aCIImage forKey:"inputImage"
  
set aOutImage to aFilter’s valueForKey:"outputImage"
  
  
— NSBitmapImageRep を CIImage から生成
  
set aRep to NSBitmapImageRep’s alloc()’s initWithCIImage:aOutImage
  
  
— NSBitmapImageRep から JPEG データを取得
  
set jpegData to aRep’s representationUsingType:(NSJPEGFileType) |properties|:(missing value)
  
  
— ファイルに保存
  
set fsRes to jpegData’s writeToFile:aPOSIX atomically:true
  
if (fsRes as boolean) = false then return false –失敗した場合
  
return aPOSIX –成功した場合
  
end convAsFilteredJPEG

–数字とアルファベットの混在状態の時にtrueを返す
on chkMixtureOfNumericAndAlphabet(checkString)
  set a0Res to chkAlphabetAndNumeric(checkString) of me
  
set a1Res to chkNumeric(checkString) of me
  
set a2Res to chkAlphabet(checkString) of me
  
if {a0Res, a1Res, a2Res} = {true, false, false} then
    return true
  else
    return false
  end if
end chkMixtureOfNumericAndAlphabet

–数字のみかを調べて返す
on chkNumeric(checkString)
  set digitCharSet to NSCharacterSet’s characterSetWithCharactersInString:"0123456789"
  
set ret to my chkCompareString:checkString baseString:digitCharSet
  
return ret as boolean
end chkNumeric

— アルファベットのみか調べて返す
on chkAlphabet(checkString)
  set aStr to NSString’s stringWithString:checkString
  
set allCharSet to NSMutableCharacterSet’s alloc()’s init()
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "a", 26))
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "A", 26))
  
set aBool to my chkCompareString:aStr baseString:allCharSet
  
return aBool as boolean
end chkAlphabet

— アルファベットと数字のみか調べて返す
on chkAlphabetAndNumeric(checkString)
  set aStr to NSString’s stringWithString:checkString
  
set allCharSet to NSMutableCharacterSet’s alloc()’s init()
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "0", 10))
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "a", 26))
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "A", 26))
  
set aBool to my chkCompareString:aStr baseString:allCharSet
  
return aBool as boolean
end chkAlphabetAndNumeric

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

–文字置換
on repChar(aStr, targStr, repStr)
  set aString to NSString’s stringWithString:aStr
  
set bString to aString’s stringByReplacingOccurrencesOfString:targStr withString:repStr
  
return bString as text
end repChar

–アルファベットと数字以外を削除して返す
on returnNumberAndAlphabetCharsOnly(aStr)
  set anNSString to NSString’s stringWithString:aStr
  
set anNSString to anNSString’s stringByReplacingOccurrencesOfString:"[^0-9A-Za-z]" withString:"" options:(NSRegularExpressionSearch) range:{0, anNSString’s |length|()}
  
return anNSString as text
end returnNumberAndAlphabetCharsOnly

★Click Here to Open This Script 

Posted in file filter geolocation Image list OCR Sandbox | Tagged 10.11savvy 10.12savvy FineReader OCR Pro | Leave a comment

ハッシュ値から、メモリースティックに保存されたReplay Dataのステージ名とプレイ日時を求める v3

Posted on 10月 30, 2018 by Takaaki Naganoya

PSPのゲーム「戦場の絆ポータブル」のセーブデータについているステージ別のプレビュー画像のハッシュ値から対戦ステージと対戦日時を抽出してタブ区切りテキストで出力するAppleScriptです。

保存された対戦データの内容を集計するために作成したものです。

PSPでメモリースティックに保存された対戦データには、すべて同じファイル名(ICON0.PNG)で異なる画像が添付されていました。ファイル名で対戦ステージを判定しようにも同じファイル名なので区別できません。

そこで、Spotlightの機能を用いて各セーブデータの「ICON0.PNG」をピックアップし、画像の内容のハッシュ値(SHA-1)を計算して、対戦ステージ内容を判定しました。

直近の対戦データをメモリースティック経由でMacに読み込み、本Scriptで分析してみたところ、

ジャブロー地上	2017年9月18日月曜日 14:42:48
ジャブロー地上	2017年9月18日月曜日 14:50:02
ジャブロー地上	2017年9月18日月曜日 14:55:22
タクラマカン砂漠	2017年9月18日月曜日 15:02:32
サイド7	2017年9月18日月曜日 15:09:36
ジャブロー地下	2017年9月18日月曜日 15:17:06
ジャブロー地上	2017年9月18日月曜日 15:31:08
サイド7	2017年9月18日月曜日 15:38:28
ジャブロー地上	2017年9月18日月曜日 15:51:52
ジャブロー地上	2018年1月2日火曜日 16:13:30
サイド7	2018年1月2日火曜日 16:23:04
ジャブロー地下	2018年1月2日火曜日 16:57:22

のようになりました。正月と秋分の日に親戚で集まったときに甥っ子と対戦した様子がありありと記録されています。

本Scriptはたまたまゲームのセーブデータの集計を行っていますが、同様の形式のデータを集計したい場合には使えそうです。

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

AppleScript名:チェックサム値から、メモリースティックに保存されたReplay Dataのステージ名とプレイ日時を求める v3.1
— Created 2015-04-17 by Takaaki Naganoya
— Modified 2018-10-29 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "md5Lib" –https://github.com/JoeKun/FileMD5Hash
use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html
use mdLib : script "Metadata Lib" version "2.0.0" –https://www.macosxautomation.com/applescript/apps/

property FileHash : a reference to current application’s FileHash
property SMSForder : a reference to current application’s SMSForder
property NSPredicate : a reference to current application’s NSPredicate
property NSFileManager : a reference to current application’s NSFileManager
property NSMutableArray : a reference to current application’s NSMutableArray

–各SAVEDATAフォルダ中の「ICON0.PNG」のSHA-1ハッシュ値とステージ名の対応表
set shaArray to NSMutableArray’s arrayWithArray:{{stageName:"ニューヤーク", sha1:"dbb9e8e26e96dbb4dd3198e55b6cde41aba8e0a8"}, {stageName:"鉱山都市", sha1:"72f35456504b1957ec85fb6a1597ac1a2baa2ee9"}, {stageName:"グレートキャニオン", sha1:"9de93e8b853fe153bc73066fb07481c774499960"}, {stageName:"サイド7", sha1:"be22fa949bfd78b0cd97596929f07ce4ec501d7b"}, {stageName:"タクラマカン砂漠", sha1:"5284dc5f0f7a53ee5677908f66da1e00b80f76b6"}, {stageName:"トリントン・タワー", sha1:"9f080853dac45ecaf1672ff2230f2b9a80a00eb4"}, {stageName:"ジャブロー地下", sha1:"a93550099419f52444cf77366773192d0bf5f848"}, {stageName:"ヒマラヤ", sha1:"877f998d608dd267c380e59a17b2a95a139baef5"}, {stageName:"ジャブロー地上", sha1:"8c4ee44e8f2fbcbf061e6d5ea2b202b08f42c59a"}}

load framework

set apPath1 to choose folder with prompt "リプレイデータが入っているフォルダを選択してください"
set aRes to perform search in folders {apPath1} predicate string "kMDItemFSName == %@" search arguments {"ICON0.PNG"}

set outList to {}
set errorList to {}

repeat with i in aRes
  set j to contents of i
  
set sumRes to (FileHash’s sha1HashOfFileAtPath:(j)) as string
  
  
–チェックサムからステージ名を検索する
  
set aPredStr to "sha1 == ’" & sumRes & "’"
  
set aPredicate to (NSPredicate’s predicateWithFormat:aPredStr)
  
set filteredArray to (shaArray’s filteredArrayUsingPredicate:aPredicate)
  
  
if filteredArray as list = {} then
    set the end of errorList to j
  else
    set tmpStage to (filteredArray’s valueForKey:"stageName") as string
    
    
set fAttrib to (NSFileManager’s defaultManager()’s attributesOfItemAtPath:j |error|:(missing value))
    
set cDat to (fAttrib’s fileCreationDate()) as date
    
    
set tmpList to {tmpStage, cDat}
    
    
if tmpList is not in outList then
      set the end of outList to tmpList
    end if
  end if
end repeat

–2D Listのソート
set sortIndexes to {1} –Key Item id: begin from 0
set sortOrders to {true} –ascending = true
set sortTypes to {"compare:"}
set out2List to (SMSForder’s subarraysIn:(outList) sortedByIndexes:sortIndexes ascending:sortOrders sortTypes:sortTypes |error|:(missing value)) as list

–2D Listをタブ区切りテキストに変換して返す
set aText to retItemDelimedAndParagraphDelimedText(out2List, tab, return) of me

–入れ子のリストを、アイテム間のデリミタとパラグラフ間のデリミタを指定してテキスト化
–というか、入れ子のリストをタブ区切りテキストにするのが目的
on retItemDelimedAndParagraphDelimedText(aList, itemDelim, paragraphDelim)
  set aText to ""
  
  
repeat with i in aList
    set aStr to retDelimedText(i, itemDelim) of me
    
set aText to aText & aStr & paragraphDelim
  end repeat
  
  
return aText
end retItemDelimedAndParagraphDelimedText

on retDelimedText(aList, aDelim)
  set aText to ""
  
set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to aDelim
  
set aText to aList as text
  
set AppleScript’s text item delimiters to curDelim
  
return aText
end retDelimedText

★Click Here to Open This Script 

Posted in file File path list Record Spotlight | Tagged 10.11savvy 10.12savvy NSFileManager NSMutableArray NSPredicate | Leave a comment

Accessibility Inspectorがv5.0にバージョンアップして使いにくく?

Posted on 10月 30, 2018 by Takaaki Naganoya


電子ブックからリンクしている情報のBlog側の欠落をチェックしていたら、このAccessibility Inspectorの情報が(Blog上に)抜けていることがわかり、埋めているわけですが………チェックしていたら、バージョンがv4.0からv5.0に上がっていることに気づきました。


▲左側がv4.0、右側がv5.0。v5.0はアプリケーションとして動作し、メニューがある


日常的にアプリケーションのGUI部品の情報を収集するのはPFiddlesoftのUI Browserで、使用率は99.9:0.1でUI Browserのほうが圧倒的に多いわけですが、ごくたまにUI Browserでは手が届かないGUI部品があります。


具体的にいえば、フローティングパレットやポップアップメニュー上の凝ったGUI部品で、これらはUI Browserではオブジェクト階層が途中で途切れているものとして表示されるため、オブジェクト階層を追跡できないことがあります。

そんなわけで、ごくたまに(1年間に1回ぐらい?)Accessibility Inspectorのごやっかいになることがあり、v4.0では問題なく使用できていました。

問題は、いつのまにかアップデートされて入っていたAccessibility Inspector v5.0。

これ、Windowの中のGUI部品は追いかけられるんですが、メニュー部品を追いかけられないように見えるのですが………。目の錯覚なのか、使いこなせていないのか現段階では不明です。

それができないと、Accessibility Inspectorの存在意義が、、、、

# メニュー項目はOption+Spaceで選択中のGUI部品への参照をAccessibility Inspector v5.0のメインウィンドウに表示できることを教えてもらいました

一応、Apple Developper Connectionのアカウントがあれば、Developperサイトにログインして、ダウンロード項目から「Accessibility Tools for Xcode – February 2012」のアーカイブをダウンロードすれば、中にAccessibility Inspector v4.0が入っています。macOS 10.12上にコピーして動かせることを確認しています。

macOS 10.14, MojaveにAccessibility Inspector v4.0をインストールして、期待どおりの動作が行えていることを確認しています。Accessibility Inspector v4.0はCode Signされていないのでシステム環境設定の「セキュリティーとプライバシー」>「アクセシビリティ」でアクセシビリティへのアクセスを許可しておく必要があります。

なお、Accessibility Inspector v4.0はCode Signされていないので、macOS 10.14, Mojave上で起動するといろいろうるさく言われますが、システム環境設定の「セキュリティーとプライバシー」>「一般」からAccessibility Inspector v4.0の起動許可を指示すれば大丈夫です。


▲macOS 10.14, Mojave上でAccessibility Inspector v4.0を起動したところ

Posted in How To Tools | Tagged 10.12savvy 10.13savvy 10.14savvy GUI Scripting | Leave a comment

【基礎】AppleScriptの実行を(操作により)中断する

Posted on 10月 30, 2018 by Takaaki Naganoya

AppleScriptの実行を途中で任意に停止したい、という場合があります。そのための方法についてまとめておきました。

# Blog消失前の投稿を再構成して「たぶんこんな内容」と推測して投稿したものです

実行を中断させる方法はいくつか存在します。ただし、そのためには「何によってAppleScriptが実行されているか」、つまり「ランタイム環境が何なのか?」を明らかにする必要があります。

AppleScriptのランタイム環境は、つきつめると数種類「しか」ないわけですが、そのランタイム環境を呼び出している側のアプリケーションにどの程度の制約を課されているか、という要素も加わってきます。

システムのあちらこちらに存在しているAppleScriptのランタイム環境のうち、ユーザーに近い部分のものについて述べることにしましょう。

ランタイム環境が「スクリプトエディタ」の場合の止め方

スクリプトエディタ上で実行中のAppleScriptは、Command-.(ピリオド)で停止できるようになっています。

ただし、すでに操作対象のアプリケーション側に制御が移っている場合には、アプリケーション側の処理が終わるまで待たされますし、アプリケーションが最前面にくるように(activate)AppleScriptが書かれていた場合には、スクリプトエディタに対して停止のキーボードショートカットを送ることは困難です。

最終的には、Command-Option-Escapeで実行中のプロセス一覧を表示させて、スクリプトエディタを強制終了させることになります。

もちろん、Terminal.app上で、Script Editor.appのプロセス番号を調べて、

% kill -7 xxx

などと野蛮な止め方をしてもよいでしょう。AppleScriptの実行を野蛮な方法で停止しても、AppleScriptの内容が壊れることはまずありません。ただし、処理していたデータは中途半端な状態のままになってしまいます。こうした処理を行う場合には、くれぐれも元データを保持しておいて、AppleScriptによる処理が失敗したり途中で停止するようなことになっても、再度実行できるようにしておきましょう。

ランタイム環境がアプレットの場合の止め方

個人的に、AppleScriptアプレットというランタイム環境はスクリプトエディタ上と挙動が変わってくるので、あまり好きではありません。それでも、タイマー割り込みやドラッグ&ドロップなどの機能を使う場合にはアプレット(ドロップレット)として保存する必要が出てきます。

アプレットの場合も、スクリプトエディタ同様Command-.(ピリオド)で止めることになりますが、たいてい止まらないのでCommand-Option-Escapeによる強制終了、あるいはターミナルから実行中のアプレットのプロセスIDを調べて強制終了、でもよいでしょう。

ランタイム環境がスクリプトメニューの場合の止め方

スクリプトメニューをどのプログラムが受け持っているか、Mac OS Xの歴史を振り返ると、いろいろ移り変わりがありました。実行するアプリケーションが単独で存在していたり、System Eventsが受け持っていたり、osascriptを呼び出していたり、ふたたび単体のアプリケーションに戻ったり。OSのバージョンを限定して話をすると、macOS 10.10〜10.13の環境ではosascriptによって実行されてきました。

スクリプトメニューからAppleScriptを実行させると、メニューに回転する歯車アイコンが表示されます。この歯車アイコンをクリックすると実行中のAppleScript一覧が表示され(複数のScriptを並行して同時に実行させることもできます)各Scriptの右下の×ボタンを押すと停止できます。

これでも止まらない場合には、Terminalからosascriptのプロセスをkillすれば大丈夫です。

macOS 10.14ではスクリプトメニューが「スクリプトメニュー」という別のアプリケーションとして実装されたので、macOS 10.14上のスクリプトメニューのランタイム環境は「スクリプトメニュー」です。Command-Option-Escapeでは終了できないので、ターミナルから「スクリプトメニュー」のプロセスIDを調べてkillすることになります。

その他の止め方

Xcode上でAppleScriptによるGUIアプリケーションを作成し、InDesignやIllustratorなどのアプリケーションを操作する処理を実行。この外部アプリケーションの操作を行う処理を止めたいといった場合もあります。

AppleScript Studioの頃とは異なり、最近のAppleScriptObjCによるGUIアプリケーション作成時には、GUIアプリケーション側と外部アプリケーション操作側は完全に分離され、後者についてはXcode上では編集すらできません。データの受け渡しはuser defaults経由で行ったりしています。

難易度の低いやり方は、外部アプリ制御側Scriptで、「処理ループ内で何らかのシグナルを監視する」というものです。特定フォルダの有無でも「メッセージ」アプリケーションのステータスメッセージでも特定Webサーバー上の特定URLのファイルでもよいのですが、それらが存在した場合には停止、というプログラム自体を組んでおきます。デスクトップ上に「Stop」という名前のフォルダが存在していたら終了、というあたりがわかりやすくて簡単な実装例でしょう。

難易度の高いやり方は、外部アプリ制御Scriptを、メモリ上に作成したOSAScriptView上で実行し、停止時にはOSAScriptControllerにstopScript:メソッドを実行するというものです。もちろん、外部アプリ制御Scriptはアプリケーションバンドル内に暗号化したファイルに保存しておき、実行時に復号化してOSAScriptViewにロードすることになります。ユーザーからの停止の仕組みを受け取るのは、Shiftキーなどのキースキャンを定期的に行うことで実現できます。

難易度の高い方が柔軟に止められますが、おすすめは難易度の低いほうです。

Posted in OSA System | 1 Comment

Post navigation

  • Older posts
  • Newer posts

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

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • macOS 15, Sequoia
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • Numbersで選択範囲のセルの前後の空白を削除
  • メキシカンハットの描画
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • AppleScriptによる並列処理
  • macOS 15でも変化したText to Speech環境
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • デフォルトインストールされたフォント名を取得するAppleScript
  • AppleScript入門③AppleScriptを使った「自動化」とは?
  • 【続報】macOS 15.5で特定ファイル名パターンのfileをaliasにcastすると100%クラッシュするバグ
  • macOS 15 リモートApple Eventsにバグ?
  • Script Debuggerの開発と販売が2025年に終了
  • AppleScript入門① AppleScriptってなんだろう?
  • macOS 14で変更になったOSバージョン取得APIの返り値
  • macOS 15:スクリプトエディタのAppleScript用語辞書を確認できない
  • NSObjectのクラス名を取得 v2.1
  • 有害ではなくなっていたSpaces
  • AVSpeechSynthesizerで読み上げテスト

Tags

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

カテゴリー

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

アーカイブ

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

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

メタ情報

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

Forum Posts

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

メタ情報

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