Menu

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

AppleScriptの穴

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

タグ: 10.14savvy

InstrumentsがAppleScriptに対応

Posted on 5月 19, 2020 by Takaaki Naganoya

InstrumentsはXcodeに同梱されているメモリ使用状況などの記録、ビジュアル化を行うツールで、アクティビティモニタの強化版といったものです。

監視対象のモジュール(Instruments)を選択してドキュメント上に配置し、監視対象プロセスを選択して記録すると、動作中のプロセスの各種リソース使用状況がわかります。

そのInstrumentsがAppleScriptに対応している(sdefを持っている)ことがわかりました(調べたことがなかった)。

Dock上でXcodeのサブメニューから起動が可能です。


▲macOS 10.14.6上で動作するInstruments version 11.3.1。バージョン番号はインストールされているXcodeと同じものを名乗っているもよう

Instrumentsを使って開発中のアプリケーションのメモリ使用状況を記録して可視化(グラフを眺めるぐらい?)してみると、ダラダラ長時間記録するよりも、目的の箇所で記録を行なったほうが使い勝手がよく、Instrumentで記録した書類が複数できてきます。

それらを選択してオープンするのに、Instruments書類(単なるログ?)はファイルサイズが巨大。これをオープンするとけっこうな処理時間がかかります。Scriptから操作できたほうがよさそうだと考えて、冗談半分でAS対応していないか調べたところ、対応していると出ました。

InstrumentsのAppleScript用語辞書の内容を見てみると、ファイルのオープン/クローズができる程度で、他に何ができるというわけでもありません。

Documentの新規作成ぐらいはできそうですが、試してみたところクラッシュします。新規作成時に、どのリソースを監視するかというモジュール(Instruments)を指定する必要があるので、ドキュメント作成時にこのInstrumentsを指定できないあたりでGUI側との機能の不一致が起こっているのでしょう。

また、ドキュメントを新規作成したあとで、個別にInstrumentsを追加できるコマンドも必要になっていくことでしょう。

AppleScript名:指定書類をオープン
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/05/19
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

set aFile to choose file

with timeout of 3600 seconds
  tell application "Instruments"
    open aFile
  end tell
end timeout

★Click Here to Open This Script 

AppleScript名:最前面のドキュメントから情報を取得
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/05/19
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

tell application "Instruments"
  tell front document
    properties
    
–> {file:file "Cherry:Users:me:Documents:Instruments_withoutRetina.trace:", modified:false, name:"Instruments_withoutRetina.trace", class:document}
    
  end tell
end tell

★Click Here to Open This Script 

AppleScript名:新規書類作成(クラッシュ)
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/05/19
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

tell application "Instruments"
  make new document –This command cause crash
end tell

★Click Here to Open This Script 

Posted in System | Tagged 10.14savvy 10.15savvy Instruments Xcode | Leave a comment

クリップボード内の文字種別を集計して円グラフ表示

Posted on 5月 16, 2020 by Takaaki Naganoya

クリップボード内に文字列が入っていれば、いいかえれば「文字列をコピーした状態であれば」、クリップボード内容をテキストとして取り出して文字種別ごとに集計して構成比を円グラフで表示するAppleScriptです。

# CAUTION: This script process Japanese characters. So, this script make no sense for other language users

グラフ表示部分は手抜きでGoogle Chartsを呼び出しているだけなので、Macがネットワークに接続されていない場合には表示できません。

macOS標準装備のScript Menuに入れて使っています。複数の円グラフを表示させることも可能なので、典型的な例文(新聞、論文、なろう系、技術系文章、文学作品)のグラフを一覧表示して、どの例文の使用比率に近いかといったことを見てわかるようにできそうです(やらないけど)。

ありものをただ引っ張り出してきて、Script文でつないだだけなので、オリジナルで記述した部分はほとんどありません。

とはいえ、技術的にはいろいろなハードルを乗り越えまくって動かしているものでもあります。

・メインスレッドでしか動かせないWkWebView、NSAlertをScriptから呼び出している(実行環境に左右されずに実行)
・Cocoa Scriptingを行うAppleScriptObjCをscript文でscript object化して(カプセル化して)呼び出し、再利用
・WkWebViewをdialog内に表示して、マウスオーバーでデータ内容が見えるようなインタラクティブなグラフを表示

といった、いろいろ無茶なことをやっているScriptです。ただ、すでに見慣れた光景になりつつありますけれども。

AppleScript名:クリップボード内の文字種別を集計して円グラフ表示.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/05/14
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use framework "WebKit"
use scripting additions

property |NSURL| : a reference to current application’s |NSURL|
property NSAlert : a reference to current application’s NSAlert
property NSString : a reference to current application’s NSString
property NSButton : a reference to current application’s NSButton
property WKWebView : a reference to current application’s WKWebView
property WKUserScript : a reference to current application’s WKUserScript
property NSURLRequest : a reference to current application’s NSURLRequest
property NSRunningApplication : a reference to current application’s NSRunningApplication
property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding
property WKUserContentController : a reference to current application’s WKUserContentController
property WKWebViewConfiguration : a reference to current application’s WKWebViewConfiguration
property NSScreenSaverWindowLevel : a reference to current application’s NSScreenSaverWindowLevel
property WKUserScriptInjectionTimeAtDocumentEnd : a reference to current application’s WKUserScriptInjectionTimeAtDocumentEnd

property returnCode : 0

–Calc Clipboard
set aRes to clipAnaliticsMain() of clipboardInfoKit
if aRes = false then return —クリップボードが空だった(文字列的に)

set totalC to totalC of aRes

set aList to {{"文字種別", "構成比"}} & rating of aRes

set aJsonArrayStr to array2DToJSONArray(aList) of me

–Pie Chart Template HTML
set myStr to "<!DOCTYPE html>
<html lang=\"UTF-8\">
<body>
<div id=\"piechart\"></div>

<script type=\"text/javascript\" src=\"https://www.gstatic.com/charts/loader.js\"></script>

<script type=\"text/javascript\">
// Load google charts
google.charts.load(’current’, {’packages’:[’corechart’]});
google.charts.setOnLoadCallback(drawChart);

// Draw the chart and set the chart values
function drawChart() {
var data = google.visualization.arrayToDataTable(%@);

// Optional; add a title and set the width and height of the chart
var options = {
is3D: true,
   ’width’:600, ’height’:400
};

// Display the chart inside the <div> element with id=\"piechart\"
var chart = new google.visualization.PieChart(document.getElementById(’piechart’));
chart.draw(data, options);
}
</script>

</body>
</html>"

set aString to current application’s NSString’s stringWithFormat_(myStr, aJsonArrayStr) as string

set paramObj to {myMessage:"文字種別構成比", mySubMessage:"クリップボードの内容を集計。文字数は" & (totalC as string) & "文字", htmlStr:aString}
–my browseStrWebContents:paramObj–for debug
my performSelectorOnMainThread:"browseStrWebContents:" withObject:(paramObj) waitUntilDone:true

on browseStrWebContents:paramObj
  set aMainMes to myMessage of paramObj
  
set aSubMes to mySubMessage of paramObj
  
set htmlString to (htmlStr of paramObj)
  
  
set aWidth to 600
  
set aHeight to 450
  
  
–WebViewをつくる
  
set aConf to WKWebViewConfiguration’s alloc()’s init()
  
  
–指定HTML内のJavaScriptをFetch
  
set jsSource to pickUpFromToStr(htmlString, "<script type=\"text/javascript\">", "</script>") of me
  
  
set userScript to WKUserScript’s alloc()’s initWithSource:jsSource injectionTime:(WKUserScriptInjectionTimeAtDocumentEnd) forMainFrameOnly:true
  
set userContentController to WKUserContentController’s alloc()’s init()
  
userContentController’s addUserScript:(userScript)
  
aConf’s setUserContentController:userContentController
  
  
set aWebView to WKWebView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight – 100)) configuration:aConf
  
aWebView’s setNavigationDelegate:me
  
aWebView’s setUIDelegate:me
  
aWebView’s setTranslatesAutoresizingMaskIntoConstraints:true
  
  
set bURL to |NSURL|’s fileURLWithPath:(POSIX path of (path to me))
  
aWebView’s loadHTMLString:htmlString baseURL:(bURL)
  
  
— set up alert  
  
set theAlert to NSAlert’s alloc()’s init()
  
tell theAlert
    its setMessageText:aMainMes
    
its setInformativeText:aSubMes
    
its addButtonWithTitle:"OK"
    
–its addButtonWithTitle:"Cancel"
    
its setAccessoryView:aWebView
    
    
set myWindow to its |window|
  end tell
  
  
myWindow’s setLevel:(NSScreenSaverWindowLevel)
  
  
— show alert in modal loop
  
NSRunningApplication’s currentApplication()’s activateWithOptions:0
  
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
  
  
–Stop Web View Action
  
set bURL to |NSURL|’s URLWithString:"about:blank"
  
set bReq to NSURLRequest’s requestWithURL:bURL
  
aWebView’s loadRequest:bReq
  
  
if (my returnCode as number) = 1001 then error number -128
end browseStrWebContents:

on doModal:aParam
  set (my returnCode) to (aParam’s runModal()) as number
end doModal:

on viewDidLoad:aNotification
  return true
end viewDidLoad:

on fetchJSSourceString(aURL)
  set jsURL to |NSURL|’s URLWithString:aURL
  
set jsSourceString to NSString’s stringWithContentsOfURL:jsURL encoding:(NSUTF8StringEncoding) |error|:(missing value)
  
return jsSourceString
end fetchJSSourceString

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

–リストを任意のデリミタ付きでテキストに
on retArrowText(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 retArrowText

on array2DToJSONArray(aList)
  set anArray to current application’s NSMutableArray’s arrayWithArray:aList
  
set jsonData to current application’s NSJSONSerialization’s dataWithJSONObject:anArray options:(0 as integer) |error|:(missing value) –0 is
  
set resString to current application’s NSString’s alloc()’s initWithData:jsonData encoding:(current application’s NSUTF8StringEncoding)
  
return resString
end array2DToJSONArray

script clipboardInfoKit
  use scripting additions
  
use framework "Foundation"
  
property parent : AppleScript
  
  
property NSString : a reference to current application’s NSString
  
property NSNumber : a reference to current application’s NSNumber
  
property NSDictionary : a reference to current application’s NSDictionary
  
property NSCountedSet : a reference to current application’s NSCountedSet
  
property NSCharacterSet : a reference to current application’s NSCharacterSet
  
property NSMutableArray : a reference to current application’s NSMutableArray
  
property NSNumberFormatter : a reference to current application’s NSNumberFormatter
  
property NSRegularExpressionSearch : a reference to current application’s NSRegularExpressionSearch
  
property NSNumberFormatterRoundUp : a reference to current application’s NSNumberFormatterRoundUp
  
property NSNumberFormatterRoundDown : a reference to current application’s NSNumberFormatterRoundDown
  
  
  
on clipAnaliticsMain()
    set cCount to 0
    
set hCount to 0
    
set kCount to 0
    
set oCount to 0
    
set tCount to 0
    
    
using terms from scripting additions
      set aStr to (the clipboard as «class utf8»)
      
if aStr = "" then
        display dialog "No text data in clipboard" buttons {"OK"} default button 1
        
return false
      end if
    end using terms from
    
    
set aRec to detectCharKindRating(aStr) of me
    
    
set cCount to cCount + (kanjiNum of aRec)
    
set hCount to hCount + (hiraganaNum of aRec)
    
set kCount to kCount + (katakanaNum of aRec)
    
set oCount to oCount + (otherNum of aRec)
    
set tCount to tCount + (totalCount of aRec)
    
    
return {rating:{{"漢字", cCount}, {"ひらがな", hCount}, {"カタカナ", kCount}, {"その他", oCount}}, totalC:tCount}
  end clipAnaliticsMain
  
  
  
  
on detectCharKindRating(aStr as string)
    set aList to NSMutableArray’s arrayWithArray:(characters of aStr)
    
set theCountedSet to NSCountedSet’s alloc()’s initWithArray:aList
    
set theEnumerator to theCountedSet’s objectEnumerator()
    
    
set cCount to 0
    
set hCount to 0
    
set kCount to 0
    
set oCount to 0
    
set totalC to length of aStr
    
    
repeat
      set aValue to theEnumerator’s nextObject()
      
if aValue is missing value then exit repeat
      
      
set aStr to aValue as string
      
set tmpCount to (theCountedSet’s countForObject:aValue)
      
      
set s1Res to chkKanji(aStr) of me
      
set s2Res to chkKatakana(aStr) of me
      
set s3Res to chkHiragana(aStr) of me
      
      
if s1Res = true then
        set cCount to cCount + tmpCount
      else if s2Res = true then
        set kCount to kCount + tmpCount
      else if s3Res = true then
        set hCount to hCount + tmpCount
      else
        set oCount to oCount + tmpCount
      end if
    end repeat
    
    
set ckRes to roundingUp((cCount / totalC) * 100, 1) of me
    
set kkRes to roundingUp((kCount / totalC) * 100, 1) of me
    
set hgRes to roundingUp((hCount / totalC) * 100, 1) of me
    
set otRes to roundingUp((oCount / totalC) * 100, 1) of me
    
    
return {kanjiNum:cCount, kanjiRating:ckRes, hiraganaNum:hCount, hiraganaRating:hgRes, katakanaNum:kCount, katakanaRating:kkRes, otherNum:oCount, otherRating:otRes, totalCount:totalC}
  end detectCharKindRating
  
  
  
on chkKanji(aChar)
    return detectCharKind(aChar, "[一-龠]") of me
  end chkKanji
  
  
on chkHiragana(aChar)
    return detectCharKind(aChar, "[ぁ-ん]") of me
  end chkHiragana
  
  
on chkKatakana(aChar)
    return detectCharKind(aChar, "[ァ-ヶ]") of me
  end chkKatakana
  
  
on detectCharKind(aChar, aPattern)
    set aChar to NSString’s stringWithString:aChar
    
set searchStr to NSString’s stringWithString:aPattern
    
set matchRes to aChar’s rangeOfString:searchStr options:(NSRegularExpressionSearch)
    
if matchRes’s location() = (current application’s NSNotFound) or (matchRes’s location() as number) > 9.99999999E+8 then
      return false
    else
      return true
    end if
  end detectCharKind
  
  
on roundingUp(aNum, aDigit as integer)
    set a to aNum as real
    
set aFormatter to NSNumberFormatter’s alloc()’s init()
    
aFormatter’s setMaximumFractionDigits:aDigit
    
aFormatter’s setRoundingMode:(NSNumberFormatterRoundUp)
    
set aStr to aFormatter’s stringFromNumber:(NSNumber’s numberWithFloat:a)
    
return (aStr as text) as real
  end roundingUp
end script

★Click Here to Open This Script 

Posted in dialog Internet JavaScript Text | Tagged 10.13savvy 10.14savvy 10.15savvy NSAlert NSButton NSCharacterSet NSCountedSet NSDictionary NSMutableArray NSNumber NSNumberFormatter NSNumberFormatterRoundDown NSNumberFormatterRoundUp NSRegularExpressionSearch NSRunningApplication NSScreenSaverWindowLevel NSString NSURL NSURLRequest NSUTF8StringEncoding WKUserContentController WKUserScript WKUserScriptInjectionTimeAtDocumentEnd WKWebView WKWebViewConfiguration | Leave a comment

システムフォントをWeightつきで指定

Posted on 5月 15, 2020 by Takaaki Naganoya

システムフォントをWeightつきで指定するAppleScriptです。

NSFontまわりの、フォント名を具体的に文字列で指定「しない」フォントの指定方法を、(必要があったので)いろいろ調べてみました。

ここに紹介したサンプルでは、System FontをWeightおよびSize指定して取得していますが、本当にやりたいのは言語(英語、日本語など)とセリフつき(Timesなど)サンセリフ(Helveticaなど)、Handwritingフォントかなどの属性情報を指定すると、なんとなくフォントを特定してくれる処理で、とてもOS内にありそうな気もするのですが、まだ見つけられておりません。

AppleScript名:システムフォントをWeightつきで指定.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/05/14
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

set aFont1 to current application’s NSFont’s systemFontOfSize:48 weight:(current application’s NSFontWeightRegular)
—> (NSFont) ".AppleSystemUIFont 48.00 pt. P [] (0x60000154c060) fobj=0x7f8bb176bfc0, spc=10.20"
set aFont1Name to aFont1’s fontName() as string
–> ".AppleSystemUIFont"

set aFont2 to current application’s NSFont’s systemFontOfSize:48 weight:(current application’s NSFontWeightUltraLight)
–> (NSFont) ".AppleSystemUIFontUltraLight 48.00 pt. P [] (0x6000012d42a0) fobj=0x7f8bb8925090, spc=10.10"
set aFont2Name to aFont2’s fontName() as string
–> ".AppleSystemUIFontUltraLight"

set aFont3 to current application’s NSFont’s systemFontOfSize:48 weight:(current application’s NSFontWeightThin)
–> (NSFont) ".AppleSystemUIFontThin 48.00 pt. P [] (0x6000013fd350) fobj=0x7f8bb3ba1140, spc=10.12"
set aFont3Name to aFont3’s fontName() as string
–> ".AppleSystemUIFontThin"

set aFont4 to current application’s NSFont’s systemFontOfSize:48 weight:(current application’s NSFontWeightLight)
–> (NSFont) ".AppleSystemUIFontLight 48.00 pt. P [] (0x6000013fd410) fobj=0x7f8bb3bbf890, spc=10.17"
set aFont4Name to aFont4’s fontName() as string
–> ".AppleSystemUIFontLight"

set aFont5 to current application’s NSFont’s systemFontOfSize:48 weight:(current application’s NSFontWeightMedium)
–> (NSFont) ".AppleSystemUIFontMedium 48.00 pt. P [] (0x60000151c8a0) fobj=0x7f8bb79289e0, spc=10.08"
set aFont5Name to aFont5’s fontName() as string
–> ".AppleSystemUIFontMedium"

set aFont6 to current application’s NSFont’s systemFontOfSize:48 weight:(current application’s NSFontWeightSemibold)
–> (NSFont) ".AppleSystemUIFontDemi 48.00 pt. P [] (0x6000013fd710) fobj=0x7f8bb69ef060, spc=9.96"
set aFont6Name to aFont6’s fontName() as string
–> ".AppleSystemUIFontDemi"

set aFont7 to current application’s NSFont’s systemFontOfSize:48 weight:(current application’s NSFontWeightBold)
–> (NSFont) ".AppleSystemUIFontBold 48.00 pt. P [] (0x600000bfa430) fobj=0x7f8bb3b55630, spc=9.84"
set aFont7Name to aFont7’s fontName() as string
–> ".AppleSystemUIFontBold"

set aFont8 to current application’s NSFont’s systemFontOfSize:48 weight:(current application’s NSFontWeightHeavy)
–> (NSFont) ".AppleSystemUIFontHeavy 48.00 pt. P [] (0x600000898a50) fobj=0x7f8bb3b79730, spc=9.66"
set aFont8Name to aFont8’s fontName() as string
–> ".AppleSystemUIFontHeavy"

set aFont9 to current application’s NSFont’s systemFontOfSize:48 weight:(current application’s NSFontWeightBlack)
–> (NSFont) ".AppleSystemUIFontBlack 48.00 pt. P [] (0x6000015a57a0) fobj=0x7f8bb14cb330, spc=9.49"
set aFont9Name to aFont9’s fontName() as string
–> ".AppleSystemUIFontBlack"

★Click Here to Open This Script 

AppleScript名:システムフォントをWeightつきで指定(monospacedDigitSystemFont).scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/05/14
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

set aFont1 to current application’s NSFont’s monospacedDigitSystemFontOfSize:16 weight:(current application’s NSFontWeightRegular)
—> (NSFont) ".SFNSText 16.00 pt. P [] (0x600001557d80) fobj=0x7f8bb7e011b0, spc=4.20"
set aFont1Name to aFont1’s fontName() as string
–> ".SFNSText"

set aFont2 to current application’s NSFont’s monospacedDigitSystemFontOfSize:16 weight:(current application’s NSFontWeightUltraLight)
–> (NSFont) ".SFNSText-Light 16.00 pt. P [] (0x6000015e08d0) fobj=0x7f8bb8914700, spc=4.02"
set aFont2Name to aFont2’s fontName() as string
–> ".SFNSText-Light"

set aFont3 to current application’s NSFont’s monospacedDigitSystemFontOfSize:16 weight:(current application’s NSFontWeightThin)
–> (NSFont) ".SFNSText-Light 16.00 pt. P [] (0x600000b789f0) fobj=0x7f8bb697f020, spc=4.02"
set aFont3Name to aFont3’s fontName() as string
–> ".SFNSText-Light"

set aFont4 to current application’s NSFont’s monospacedDigitSystemFontOfSize:16 weight:(current application’s NSFontWeightLight)
–> (NSFont) ".SFNSText-Light 16.00 pt. P [] (0x6000015a3c90) fobj=0x7f8bb88c2130, spc=4.02"
set aFont4Name to aFont4’s fontName() as string
–> ".SFNSText-Light"

set aFont5 to current application’s NSFont’s monospacedDigitSystemFontOfSize:16 weight:(current application’s NSFontWeightMedium)
–> (NSFont) ".SFNSText-Medium 16.00 pt. P [] (0x6000014667f0) fobj=0x7f8bb891bdd0, spc=4.06"
set aFont5Name to aFont5’s fontName() as string
–> ".SFNSText-Medium"

set aFont6 to current application’s NSFont’s monospacedDigitSystemFontOfSize:16 weight:(current application’s NSFontWeightSemibold)
–> (NSFont) ".SFNSText-Semibold 16.00 pt. P [] (0x6000014b7120) fobj=0x7f8bb8866210, spc=3.95"
set aFont6Name to aFont6’s fontName() as string
–> ".SFNSText-Semibold"

set aFont7 to current application’s NSFont’s monospacedDigitSystemFontOfSize:16 weight:(current application’s NSFontWeightBold)
–> (NSFont) ".SFNSText-Bold 16.00 pt. P [] (0x600001412dc0) fobj=0x7f8bb8920310, spc=3.81"
set aFont7Name to aFont7’s fontName() as string
–> ".SFNSText-Bold"

set aFont8 to current application’s NSFont’s monospacedDigitSystemFontOfSize:16 weight:(current application’s NSFontWeightHeavy)
–> (NSFont) ".SFNSText-Heavy 16.00 pt. P [] (0x600001443720) fobj=0x7f8bb6cea5f0, spc=3.61"
set aFont8Name to aFont8’s fontName() as string
–> ".SFNSText-Heavy"

set aFont9 to current application’s NSFont’s monospacedDigitSystemFontOfSize:16 weight:(current application’s NSFontWeightBlack)
–> (NSFont) ".SFNSText-Heavy 16.00 pt. P [] (0x60000145b5d0) fobj=0x7f8bb6996ff0, spc=3.61"
set aFont9Name to aFont9’s fontName() as string
–> ".SFNSText-Heavy"

★Click Here to Open This Script 

Posted in Font System | Tagged 10.13savvy 10.14savvy 10.15savvy NSFont | Leave a comment

Switch Controlを起動

Posted on 5月 13, 2020 by Takaaki Naganoya

Switch Controlを起動するAppleScriptです。macOS標準搭載のScript Menuに入れて呼び出して使っています。Switch Controlは、障害者向けの支援機能を提供するmacOSの標準機能で、標準のマウス/トラックパッド、キーボードなどの利用が困難なユーザーに向けて少ないボタンや音声で操作する機能を提供するものです。

一般のユーザーにとってもSwitch Controlは有効活用できる機能であるため、個人的にいろいろ試しています。

もともと、Switch Controlを起動するためのコマンドは用意されていません。AppleScriptのコマンドで起動できるとか、コマンドラインから起動できるとかいった手軽な起動手段は存在していません。

……というわけで、仕方なくGUI Scriptingで画面上のチェックボックスをクリックするという不毛な処理を書いたわけですが、ただダラダラとGUI部品の階層をなぞるだけの知性のカケラもないコードを書くだけでは意味がありません。

この、クリックする対象のチェックボックスを実行言語環境が変わっても自動で検出できるようにチャレンジしてみました。

結果:失敗 追いかける対象が大きすぎたようです。システム環境設定の画面上のチェックボックスについているタイトル文字を特定するだけの話なのですが、システム環境設定(System Preferences.app)の各機能はプラグインで提供されており、システム環境設定のバンドル内のstringsファイルを追いかけても希望の文字列は得られません。

# このため、チェックボックスのタイトルを言語環境ごとに書き換える必要があります

では、実際に各プラグインのバンドル構造内でstringsファイルを取得することを試みたのですが、これにも失敗。それらしい文字列は得られるものの、文章すべてが1エントリに登録されているわけではないようで、stringsファイルでキーを指定すれば各ロケールごとの対象文字列が得られる……という理想的な処理はできませんでした。

今回のアプローチは技術的には失敗してしまいましたが、他の誰かが突破する日も来るかもしれません。自分のマシンのSSD内には、割とそうした「失敗作」のScriptも存在しており、そうした失敗作が別の機会の土台になることも多々あります。

仕事で作り込む必要のあるScriptであれば、スクリプトバンドル内に各言語ごとの文字列テーブルを自分で作って、localized stringでその値を引けるようにする感じでしょうか。OS側で対象箇所の文言を変更した場合には自分のテーブル側もアップデートする必要が出てきてしまいます。

本Scriptの冒頭でSwitch Controlが起動しているかどうかのチェックを行い、起動中であれば起動処理を行わないようにしています。この判定処理自体は、単体ではほぼ意味がありませんが、こうして組み合わせることで「不要な処理を行わない」ための部品として有効に活用できているといえます。

AppleScript名:Switch Controlを起動
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/05/13
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

set aRes to launchSwitchControl() of me

on launchSwitchControl()
  if current application’s NSWorkspace’s sharedWorkspace()’s isSwitchControlEnabled() = true then return true
  
set aLoc to (current application’s NSLocale’s currentLocale()’s languageCode()) as string
  
  
–Current Language detection
  
if aLoc = "en" then
    set aStr to "Enable Switch Control" –English
  else if aLoc = "ja" then
    set aStr to "スイッチコントロールを有効にする" –Japanese
  else
    error "Make current language entry"
  end if
  
  
tell application "System Preferences"
    activate
    
tell pane id "com.apple.preference.universalaccess"
      reveal anchor "Switch"
    end tell
  end tell
  
  
set hitF to false
  
  
tell application "System Events"
    tell process "System Preferences"
      repeat 200 times
        delay 0.1
        
if (exists checkbox aStr of tab group 1 of group 1 of window 1) then
          click checkbox aStr of tab group 1 of group 1 of window 1
          
set hitF to true
          
exit repeat
        end if
      end repeat
    end tell
  end tell
  
  
tell application "System Preferences" to quit
  
return hitF
end launchSwitchControl

★Click Here to Open This Script 

Posted in GUI Scripting | Tagged 10.14savvy 10.15savvy Switch Control System Events | Leave a comment

New eBook “Switch Control with AppleScript” now on sale

Posted on 5月 12, 2020 by Takaaki Naganoya


This ebook “Switch Control with AppleScript” is a book about Switch Control. 89 pages (today). Price: JPY 3,000.

It is one of accessibility function for people with disabiulities. But it is very useful for every macOS users specially for the scripters.

Switch Control can launch AppleScript or run keyboard shortcut sequence. We can make button-based simple GUI for AppleScript. It is the easiest environent to make GUI.

This book will contain author’s sample Switch Control. It is useful and gives you a power of automation for macOS users.


▲supplement sample Switch Control Panel


▲supplement sample Switch Control Panel

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

面積で評価して、Keynoteのメインウィンドウのうち最大のもののItem Numberを返す

Posted on 5月 10, 2020 by Takaaki Naganoya

ウィンドウ上に複数存在するscroll areaのうち処理対象となるべきものを面積を計算することで特定するGUI Scripting系のAppleScriptです。

どーしてもGUI Scriptingでしか操作できない機能があって、それを自動化する価値があって、大幅に発生する可能性の高い労力を削減できる見込みが立ったので、一気に自動化Scriptを作成。本Scriptはその中で作成した1つの部品です。

自分が書いた処理内容は、Keynoteで作った書類の目次ページに用意した、各スライドのタイトルに実際のスライドへのリンクを付加するもの。

本来、Keynote自体のAppleScript用語辞書に標準装備されていてほしい機能です。残念ながら標準装備されていないために、自分で組む必要があったわけです。

それを作っている途中で、このメインの(Keynoteオブジェクトを配置する中央のエリア)scroll areaのIDが起動するたびに変わるという現象に直面。初期状態(インスペクタの表示状態)をそろえてもIDが変わる。たいていこうしたGUI Scriptingがらみの「怪奇現象」に直面した場合には、スクルプトエディタやアプリケーションの再起動を行えば回避できることが多いのですが、何回かためしても回避できなかったので、scroll areaの特定をID以外で行うことに。

IDが毎回(起動ごとに)変更になるので、「最大の面積を持つもの」を計算して求めるようにしてみました。

AppleScript名:面積で評価して、Keynoteのメインウィンドウのうち最大のもののItem Numberを返す
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/05/09
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

set areaNum to getKenoteScrollAreaMax() of me

–面積で評価して、Keynoteのメインウィンドウのうち最大のもののItem Numberを返す
on getKenoteScrollAreaMax()
  tell application "System Events"
    tell process "Keynote"
      tell window 1
        set sCount to count every scroll area
        
set tmpMax to 0
        
set tmpMaxItem to 0
        
repeat with i from 1 to sCount
          tell scroll area i
            set tmpA to size
            
copy tmpA to {tmpW, tmpH}
            
set tmpArea to tmpW * tmpH
            
if tmpArea > tmpMax then
              set tmpMax to tmpArea
              
set tmpMaxItem to i
            end if
          end tell
        end repeat
      end tell
    end tell
  end tell
  
  
return tmpMaxItem
end getKenoteScrollAreaMax

★Click Here to Open This Script 

Posted in GUI Scripting | Tagged 10.13savvy 10.14savvy 10.15savvy Keynote System Events | Leave a comment

アラートダイアログ上にWebViewでGoogle Chartsを表示(Calendar Chart)

Posted on 5月 7, 2020 by Takaaki Naganoya

アラートダイアログ上にWkWebViewを配置し、Google Chartsを用いてCalendar Chartを表示するAppleScriptです。

自分の開発環境(MacBook Pro Retina 2012, Core i7 2.6GHz)で100日間のアクセス履歴を処理して7秒強ぐらいで描画が終了します。

調子に乗って300日分のアクセス履歴を処理したところ、表示まで1分ほどかかりました。あまり長い期間の描画を行わせるのは(このプログラムの書き方だと)向いていないと感じます。いまのところテストしただけで実用性は考えていませんが、この程度のグラフなら自前でNSImage上にボックスを描画して表示しても大した手間にはならないでしょう。


▲スクリプトエディタ上で実行したところ


▲Script Debugger上で実行したところ


▲スクリプトメニュー上で実行したところ

Safariのアクセス履歴は例によってsqliteのDatabaseにアクセスして取得していますが、AppleScriptのランタイム環境によっては、アクセス権限がないというメッセージが出てアクセスできないことがあります。ASObjC Explorer 4上では実行できませんでしたし、Switch Control上でも実行できません。

# 管理者権限つきで実行しても(with administrator privileges)実行できません → Switch Controlでも実行できるようになりました

最初に掲載したバージョンでは、グラフ化したときに表示月が1か月ズレるという問題がありました。

Google Chartsのドキュメントを確認したところ、

Note: JavaScript counts months starting at zero: January is 0, February is 1, and December is 11. If your calendar chart seems off by a month, this is why.

JavaScriptでMonthはJanuaryが0らしく、monthを-1する必要があるとdocumentに書かれていました。うわ、なにその仕様?(ーー;;;

AppleScript名:アラートダイアログ上にWebViewでGoogle Chartを表示(Calendar Charts)v1a.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/05/07
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use framework "WebKit"
use scripting additions

property |NSURL| : a reference to current application’s |NSURL|
property NSAlert : a reference to current application’s NSAlert
property NSString : a reference to current application’s NSString
property NSButton : a reference to current application’s NSButton
property WKWebView : a reference to current application’s WKWebView
property WKUserScript : a reference to current application’s WKUserScript
property NSURLRequest : a reference to current application’s NSURLRequest
property NSRunningApplication : a reference to current application’s NSRunningApplication
property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding
property WKUserContentController : a reference to current application’s WKUserContentController
property WKWebViewConfiguration : a reference to current application’s WKWebViewConfiguration
property WKUserScriptInjectionTimeAtDocumentEnd : a reference to current application’s WKUserScriptInjectionTimeAtDocumentEnd

property returnCode : 0

script spd
  property aRes : {}
  
property bRes : {}
end script

–Calculate Safari access frequency for (parameter days)
set (aRes of spd) to calcMain(100) of safariHistLib

set (bRes of spd) to ""
repeat with i in (aRes of spd)
  set {item1, item2, item3} to parseByDelim(theName of (contents of i), "-") of me
  
set newLine to " [ new Date(" & (item1 as string) & ", " & ((item2 – 1) as string) & ", " & (item3 as string) & "), " & (numberOfTimes of i) & "]," & (string id 10)
  
set (bRes of spd) to (bRes of spd) & newLine
end repeat

set (bRes of spd) to text 1 thru -3 of (bRes of spd)

–Pie Chart Template HTML
set myStr to "<!DOCTYPE html>
<html lang=\"UTF-8\">
<head>
<div id=\"calendarchart\"></div>

<script type=\"text/javascript\" src=\"https://www.gstatic.com/charts/loader.js\"></script>

<script type=\"text/javascript\">
// Load google charts
google.charts.load(’current’, {’packages’:[’calendar’]});
google.charts.setOnLoadCallback(drawChart);

// Draw the chart and set the chart values
function drawChart() {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: ’date’, id: ’Date’ });
dataTable.addColumn({ type: ’number’, id: ’Web Access’ });
dataTable.addRows([
  %@
]);

var chart = new google.visualization.Calendar(document.getElementById(’calendar_basic’));

var options = {
title: \"Web Activity\",
height: 350,
};

chart.draw(dataTable, options);
}
</script>
</head>
<body>
  <div id=\"calendar_basic\" style=\"width: 1000px; height: 350px;\"></div>
</body>
</html>"

set aString to current application’s NSString’s stringWithFormat_(myStr, (bRes of spd)) as string

set paramObj to {myMessage:"Calendar Chart Test", mySubMessage:"This is a simple calendar chart using google charts", htmlStr:aString}
–my browseStrWebContents:paramObj–for debug
my performSelectorOnMainThread:"browseStrWebContents:" withObject:(paramObj) waitUntilDone:true

on browseStrWebContents:paramObj
  set aMainMes to myMessage of paramObj
  
set aSubMes to mySubMessage of paramObj
  
set htmlString to (htmlStr of paramObj)
  
  
set aWidth to 1000
  
set aHeight to 300
  
  
–WebViewをつくる
  
set aConf to WKWebViewConfiguration’s alloc()’s init()
  
  
–指定HTML内のJavaScriptをFetch
  
set jsSource to pickUpFromToStr(htmlString, "<script type=\"text/javascript\">", "</script>") of me
  
  
set userScript to WKUserScript’s alloc()’s initWithSource:jsSource injectionTime:(WKUserScriptInjectionTimeAtDocumentEnd) forMainFrameOnly:true
  
set userContentController to WKUserContentController’s alloc()’s init()
  
userContentController’s addUserScript:(userScript)
  
aConf’s setUserContentController:userContentController
  
  
set aWebView to WKWebView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight – 100)) configuration:aConf
  
aWebView’s setNavigationDelegate:me
  
aWebView’s setUIDelegate:me
  
aWebView’s setTranslatesAutoresizingMaskIntoConstraints:true
  
  
set bURL to |NSURL|’s fileURLWithPath:(POSIX path of (path to me))
  
aWebView’s loadHTMLString:htmlString baseURL:(bURL)
  
  
— set up alert  
  
set theAlert to NSAlert’s alloc()’s init()
  
tell theAlert
    its setMessageText:aMainMes
    
its setInformativeText:aSubMes
    
its addButtonWithTitle:"OK"
    
–its addButtonWithTitle:"Cancel"
    
its setAccessoryView:aWebView
    
    
set myWindow to its |window|
  end tell
  
  
— show alert in modal loop
  
NSRunningApplication’s currentApplication()’s activateWithOptions:0
  
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
  
  
–Stop Web View Action
  
set bURL to |NSURL|’s URLWithString:"about:blank"
  
set bReq to NSURLRequest’s requestWithURL:bURL
  
aWebView’s loadRequest:bReq
  
  
if (my returnCode as number) = 1001 then error number -128
end browseStrWebContents:

on doModal:aParam
  set (my returnCode) to (aParam’s runModal()) as number
end doModal:

on viewDidLoad:aNotification
  return true
end viewDidLoad:

on fetchJSSourceString(aURL)
  set jsURL to |NSURL|’s URLWithString:aURL
  
set jsSourceString to NSString’s stringWithContentsOfURL:jsURL encoding:(NSUTF8StringEncoding) |error|:(missing value)
  
return jsSourceString
end fetchJSSourceString

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

–リストを任意のデリミタ付きでテキストに
on retArrowText(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 retArrowText

on array2DToJSONArray(aList)
  set anArray to current application’s NSMutableArray’s arrayWithArray:aList
  
set jsonData to current application’s NSJSONSerialization’s dataWithJSONObject:anArray options:(0 as integer) |error|:(missing value) –0 is
  
set resString to current application’s NSString’s alloc()’s initWithData:jsonData encoding:(current application’s NSUTF8StringEncoding)
  
return resString
end array2DToJSONArray

on parseByDelim(aData, aDelim)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to aDelim
  
set dList to text items of aData
  
set AppleScript’s text item delimiters to curDelim
  
return dList
end parseByDelim

script safariHistLib
  property parent : AppleScript
  
use scripting additions
  
use framework "Foundation"
  
  
property |NSURL| : a reference to current application’s |NSURL|
  
  
script spd
    property sList : {}
    
property nList : {}
    
property sRes : {}
    
property dRes1 : {}
    
property dRes2 : {}
  end script
  
  
  
on calcMain(daysNum)
    set (dRes1 of spd) to dumpSafariHistoryFromDaysBefore(daysNum) of me
    
    
set (dRes2 of spd) to {}
    
repeat with i in (dRes1 of spd)
      copy (first item of i) as string to dStr
      
set convDstr to first item of (parseByDelim(dStr, {" "}) of me)
      
set the end of (dRes2 of spd) to convDstr
    end repeat
    
    
–日付ごとに登場頻度集計
    
set cRes to countItemsByItsAppearance2((dRes2 of spd)) of me
    
return cRes as list
  end calcMain
  
  
  
–NSArrayに入れたレコードを、指定の属性ラベルの値でソート
  
on sortRecListByLabel(aArray, aLabelStr as string, ascendF as boolean)
    –ソート
    
set sortDesc to current application’s NSSortDescriptor’s alloc()’s initWithKey:aLabelStr ascending:ascendF
    
set sortDescArray to current application’s NSArray’s arrayWithObjects:sortDesc
    
set sortedArray to aArray’s sortedArrayUsingDescriptors:sortDescArray
    
    
–NSArrayからListに型変換して返す
    
set bList to (sortedArray) as list
    
return bList
  end sortRecListByLabel
  
  
  
on dumpSafariHistoryFromDaysBefore(daysBefore)
    –現在日時のn日前を求める
    
using terms from scripting additions
      set origDate to (current date) – (daysBefore * days)
    end using terms from
    
    
set dStr to convDateObjToStrWithFormat(origDate, "yyyy-MM-dd hh:mm:ss") of me
    
    
set aDBpath to "~/Library/Safari/History.db"
    
set pathString to current application’s NSString’s stringWithString:aDBpath
    
set newPath to pathString’s stringByExpandingTildeInPath()
    
    
set aText to "/usr/bin/sqlite3 " & newPath & " ’SELECT datetime(history_visits.visit_time+978307200, \"unixepoch\", \"localtime\"), history_visits.title || \" @ \" || substr(history_items.URL,1,max(length(history_items.URL)*(instr(history_items.URL,\" & \")=0),instr(history_items.URL,\" & \"))) as Info FROM history_visits INNER JOIN history_items ON history_items.id = history_visits.history_item where history_visits.visit_time>(julianday(\"" & dStr & "\")*86400-211845068000) ORDER BY visit_time ASC LIMIT 999999;’"
    
    
using terms from scripting additions
      set (sRes of spd) to do shell script aText
    end using terms from
    
    
set (sList of spd) to (paragraphs of (sRes of spd))
    
    
repeat with i in (sList of spd)
      set j to contents of i
      
      
–Parse each field
      
set j2 to parseByDelim(j, {"|", "@ "}) of me
      
      
set the end of (nList of spd) to j2
    end repeat
    
    
return (nList of spd)
  end dumpSafariHistoryFromDaysBefore
  
  
  
  
on parseByDelim(aData, aDelim)
    set curDelim to AppleScript’s text item delimiters
    
set AppleScript’s text item delimiters to aDelim
    
set dList to text items of aData
    
set AppleScript’s text item delimiters to curDelim
    
return dList
  end parseByDelim
  
  
  
–出現回数で集計
  
on countItemsByItsAppearance2(aList)
    set aSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList
    
set bArray to current application’s NSMutableArray’s array()
    
set theEnumerator to aSet’s objectEnumerator()
    
    
repeat
      set aValue to theEnumerator’s nextObject()
      
if aValue is missing value then exit repeat
      
bArray’s addObject:(current application’s NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{"theName", "numberOfTimes"})
    end repeat
    
    
–出現回数(numberOfTimes)で降順ソート
    
set theDesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:"theName" ascending:true
    
bArray’s sortUsingDescriptors:{theDesc}
    
    
return bArray
  end countItemsByItsAppearance2
  
  
  
on convDateObjToStrWithFormat(aDateO as date, aFormatStr as string)
    set aDF to current application’s NSDateFormatter’s alloc()’s init()
    
    
set aLoc to current application’s NSLocale’s currentLocale()
    
set aLocStr to (aLoc’s localeIdentifier()) as string
    
    
aDF’s setLocale:(current application’s NSLocale’s alloc()’s initWithLocaleIdentifier:aLocStr)
    
aDF’s setDateFormat:aFormatStr
    
set dRes to (aDF’s stringFromDate:aDateO) as string
    
return dRes
  end convDateObjToStrWithFormat
  
end script

★Click Here to Open This Script 

Posted in JavaScript shell script Sort | Tagged 10.13savvy 10.14savvy 10.15savvy NSAlert NSButton NSRunningApplication NSString NSURL NSURLRequest NSUTF8StringEncoding Safari WKUserContentController WKUserScript WKUserScriptInjectionTimeAtDocumentEnd WKWebView WKWebViewConfiguration | Leave a comment

指定アプリケーションを指定言語環境で再起動 v3

Posted on 5月 6, 2020 by Takaaki Naganoya

指定アプリケーションを、現在のユーザーアカウントで指定可能な言語環境を指定して再起動するAppleScriptの改良版です。

初版では言語環境を選んでからアプリケーションを選んでいましたが、この順番を逆にしました。アプリケーションを選択し、そのバンドル内のローカライズ状況を調べ、一覧から選択して起動します。


▲最初にアプリケーションを選択


▲Keynoteのローカライズ言語一覧から対象言語コードを選択


▲アラビア語環境で起動させたKeynote


▲タイ語環境で起動させたKeynote


▲ロシア語環境で起動させたKeynote


▲中国語(簡体字)環境で起動させたKeynote

個人的には割と実用性が高いScriptです。

AppleScript名:指定アプリケーションの指定言語環境で再起動 v3.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/05/06
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"

property |NSURL| : a reference to current application’s |NSURL|
property NSBundle : a reference to current application’s NSBundle
property NSWorkspace : a reference to current application’s NSWorkspace

set anApp to path to (choose application)

tell application "Finder"
  set aBundle to properties of anApp
  
set targID to id of aBundle –Get Bundle ID
end tell

set bRes to getLocalizationsFromBundleID(targID) of me
set cRes to my sort1DList:bRes ascOrder:true

set dRes to (choose from list cRes)
if dRes = missing value or dRes = false then return

set targLanguage to first item of dRes

set appPath to retPathFromBundleID(targID) of me

set sText to "open -n -a " & quoted form of appPath & " –args -AppleLanguages ’(\"" & targLanguage & "\")’"
do shell script sText

on getLocalizationsFromBundleID(aBundleID)
  set aRes to retPathFromBundleID(aBundleID) of me
  
if aRes = false then error "Wrong Bundle ID."
  
return getSpecifiedAppFilesLocalizationListWithDuplication(aRes) of me
end getLocalizationsFromBundleID

–指定アプリケーションファイルの、指定Localeにおけるローカライズ言語リストを求める。重複を許容
on getSpecifiedAppFilesLocalizationListWithDuplication(appPOSIXpath)
  set aURL to (|NSURL|’s fileURLWithPath:appPOSIXpath)
  
set aBundle to NSBundle’s bundleWithURL:aURL
  
set locList to aBundle’s localizations()
  
return locList as list
end getSpecifiedAppFilesLocalizationListWithDuplication

on retPathFromBundleID(aBundleID)
  set aURL to NSWorkspace’s sharedWorkspace()’s URLForApplicationWithBundleIdentifier:aBundleID
  
if aURL = missing value then return false –Error
  
return aURL’s |path|() as string
end retPathFromBundleID

–1D Listをsort / ascOrderがtrueだと昇順ソート、falseだと降順ソート
on sort1DList:theList ascOrder:aBool
  set aDdesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:"self" ascending:aBool selector:"localizedCaseInsensitiveCompare:"
  
set theArray to current application’s NSArray’s arrayWithArray:theList
  
return (theArray’s sortedArrayUsingDescriptors:{aDdesc}) as list
end sort1DList:ascOrder:

★Click Here to Open This Script 

Posted in Locale | Tagged 10.13savvy 10.14savvy 10.15savvy Finder NSBundle NSURL NSWorkspace | Leave a comment

Keynoteのselectionの使い方が判明

Posted on 5月 4, 2020 by Takaaki Naganoya

AppleScriptにおける「selection」という予約語は割と重要で、選択中のオブジェクトや選択中のテキストを特定したり、選択中のオブジェクトへの処理を行うといった、一歩踏み出した処理が行えます。

KeynoteのAppleScript用語辞書に「selection」が追加されたのは、2019年3月にリリースされたv9.0のこと。

「list of iWork item」を返してくると記載されていることから、スライド(ページ)上で選択中の各種iWork item(shapeとかimageとかtext itemなどの各種オブジェクト)の選択状態を取得できることが期待されたわけですが、実際に試してみるとAppleScript用語辞書のようにiWork itemsを取得できるわけではありませんでした(当時のガッカリ感が半端ない)。

ところが、些細なことからこのKeynoteのselectionが「何を」選択しているかを返すかが分かってきました。

この、ウィンドウ左側のアウトライン表示されている各スライド(ページ)。ここを複数選択した状態でselectionを実行すると、このスライドがlistで返ってくることがわかりました。

この動作を知らずに(KeynoteのAppleScriptの用語辞書を信用して)試すと、現在表示中のスライド(ページ)のオブジェクトがリストで返ってくるという動作になります。なので、このselectionは現在表示中のスライド(ページ)のオブジェクトを返す(超使えない)コマンドだと判断していました。

ウィンドウ内容の表示ポップアップから「Light Table」を選択すると、

各スライドのサムネールが一覧表示されますが、

ここで複数スライドを選択しても「selection」で選択状態を取得できるわけではないようです。

Keynoteに対するAppleScriptの処理で、スライド上の各種オブジェクトの位置やサイズを統一するようなものがありますが、そういう範囲で使うのであれば有効に使えるといったところでしょうか。

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

Early access program : ebook “Switch Control with AppleScript”

Posted on 5月 4, 2020 by Takaaki Naganoya


This is an early access program. This ebook is in progress, not finished. The early access reader can read it with agreement. The early access readers can make request to author during works (every request will be discussed, without 100% guarantee to be realized). 65 pages (today). Price: JPY 3,000.

This ebook “Switch Control with AppleScript” is a book about Switch Control. It is one of accessibility function for people with disabiulities. But it is very useful for every macOS users specially for the scripters.

Switch Control can launch AppleScript or run keyboard shortcut sequence. We can make button-based simple GUI for AppleScript. It is the easiest environent to make GUI.

This book will contain author’s sample Switch Control. It is useful and gives you a power of automation for macOS users.

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

Switch Controlがオンになっているか調べる

Posted on 5月 3, 2020 by Takaaki Naganoya

Switch Controlが起動中かどうかをNSWorkspace経由で調べるAppleScriptです。

いろいろなAppleScriptをSwitch Controlのパネルに盛り込んで利用していますが、けっこう使いでがあっていい感じです。Script MenuにAppleScriptを入れて呼び出すのも実用性が高くてよいのですが、Switch Controlのパネルに入れると常時フローティングパネルで表示される(消したり最小化も可)ため、アプリケーションの機能が不完全であると感じるところをユーザーが自分で勝手に補える感覚がとてもいい感じです。

ただ、1つ問題があるとすれば、Switch Controlをプログラム側から起動する方法が公開されていないようである点。本Scriptのように、起動中であることを判定する方法は提供されているのですが。

Switch Control(=AssistiveControl)がオンになっていると、InputManager側から見えるので

このあたりに解決の鍵がありそうな気もします。ただ、文字入力に介在できる機能でもあるため、セキュリティ上の懸念から「あえて」そうしたAPIを公開していないのかも。

現状では唯一、GUI Scriptingで野蛮にチェックボックスをクリックするか、あるいいはチェックボックスの値を変更するぐらいでしょう。実際に試してはいないので、これもできるか100%の保証があるものではありませんけれども。

AppleScript名:スイッチコントロールがオンになっているか調べる.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/01/02
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

current application’s NSWorkspace’s sharedWorkspace()’s isSwitchControlEnabled()
–> true / false

★Click Here to Open This Script 

Posted in System | Tagged 10.13savvy 10.14savvy 10.15savvy NSWorkspace Switch Control | Leave a comment

Kamenoko、Mac App Storeで販売開始

Posted on 5月 3, 2020 by Takaaki Naganoya

Mac App Storeでリジェクトをくらうこと3回。ようやくKamenokoがMac App Storeで販売開始になりました。本アプリケーションは、Piyomaru SoftwareがAppleScriptで開発し、Mac App Storeで販売したアプリケーションの2作品目になります。

# Mac App Storeからちゃんと買えることを確認しました。こういうの、1つ1つ確認しないと怖いです

1つやらかしたのは、検索キーワードにアプリケーション名を入れておかなかったので、アプリケーション名で検索できないという「お可愛らしい」ミス。

些細な機能のアップデートをリリースしてキーワードを追加しておくほかなさそうです。

# v1.1のリリース時にいろいろ宣伝を(人力で)行うことにします。このv1.1で安定性と速度が大幅に向上し(このあたりはプログラム以外の要素による)、簡易Undoや入力ダイアログの文字化け抑止など、完成度が大幅に増しています。Mac Pro 2019で計算間違いが起こる現象についても対処を行なっています(実機がないので検証は行えないんですけれども)

最初のバージョンなので、メニューなどは日本語ローカライズしていません。

また、中身がほぼ99.9%AppleScriptで書いてあるものの、

Scriptableではありません。このアプリケーションの特性からいって、アプリケーションの書類を操作(読み書き)できるAppleScriptライブラリをアプリケーションバンドル内に入れることで、アプリケーション自体をScriptableにしなくても書類を操作できてよいのではないかと考えています。

主要機能をコンテクストメニューから呼び出すので、ワンボタンマウスを使うと手も足も出ません。その点のみ要注意です。

本アプリケーションで苦労した点

もともと、この6角形の図形を使ってKeynote上でいろいろアイデアを練ったり説明のための図を作っていろいろ試してみたら「この図を作るアプリケーションは便利だし、自分でも作れそうだ」と思いついたのがきっかけです。


▲LGやPanasonicが出している透明有機ELディスプレイに表示させるとこんな感じに?(想像図)

ハリウッド映画に出てくるハリウッド的な未来風のインタフェースを実際に実装してみるとこんな感じになるだろうか、というコンセプトでデザインしています。


▲Panasonic様のショールームを訪問して、実機で表示してみたところ

透明ディスプレイでは、明暗差を大きく確保しないとオブジェクトの視認性が下がるとか、グラデーション表現を行うと視認性が下がるといった「仮説」を立て、なるべく一色でベタ塗りするように味付けしています。このあたりは、透明ディスプレイに合わせたチューニングです。グリーンバック表示機能も、どの程度使えるか不明ですが、黒色バック透過モードで使い勝手がよくなかった場合への備えでもあります(一説には、黒色バック透過が一番きれいに透過するもよう)。

濃い色を積極的に使っているのも、透明ディスプレイの透過モード時には全体的に白っぽく表示される傾向があるようなので、「白飛び」を避けることが目的です。

1月中旬ぐらいに作り始め、1月末には初期バージョンが動いていました。


▲初期バージョン


▲セルのダブルクリックで文字入力が可能に(2月中旬)


▲指定セル内キーワードのタクソノミー展開を実装(2月中旬)


▲ビューの拡大・縮小表示、コンテクストメニュー表示が可能に(2月末)


▲ブロック認識、ブロック削除が可能に(3月中旬)


▲AirDrop共有、データ埋め込みPNG書き出し(3月中旬)


▲テーマセレクタが完成(3月下旬)


▲大型文字入力ダイアログを追加(4月)

正直なところ、こんなストロングスタイルのGUIアプリケーションを作ろうと思ったことはなかったので、いろいろと未知の現象に直面しました。

一番真っ青になったのは、開発途上でド派手なメモリリークに直面したときです。たいていのAppleScriptアプリケーションは、まとまった処理を行うためのパラメータ選択をGUI画面上で行い、メイン処理が動いたらまとまった処理を行って終了という動き方をするものでした。つまり、GUIアプリケーションといいつつもメモリリークに苦しめられることが少なかったのです。

こんな風にユーザーと対話動作をたえず行い、結果をグラフィックとして画面に描画する(=メモリリークの危険性の高い)アプリケーションを作るのははじめてです。

まずは、些細な処理でWindow Serverのメモリを大量に消費してクラッシュするという現象に直面。開発初期にこの現象の対策が行えたことはラッキーでした(Edama2さんにはこの段階でいろいろ助言をいただきました)。

次に、プレビュー作成時にメモリリークを行う現象に直面。いくぶん緩和していますが、ここは解決できていません。クラッシュしても、作業中の内容を定期的に保存し、強制終了後の再起動時にデータをリカバリする機能を追加。クラッシュしにくくする方向の努力はしつつも、クラッシュしてもデータを失いにくい方向に機能強化しました。

環境設定まわりの機能はけっこう実装に苦労しています。実装が間に合わなかったので、仕様的には幾分日和りました。

そして、毎度毎度のことながらSandbox化には苦しみました。コード署名するのに、Mac App Installerの署名とMac App IDの署名があり、間違ってMac App Installerで署名したり。あとは、コマンドラインから起動するタイプのツールをアプリケーションバンドル内に同梱して呼び出していたのですが(display mirror)、コードサインで問題が出たので分離せずにアプリケーション内に組み込むように変更しました(リジェクトされている間に機能改変)。

本アプリケーションでプログラム的に一番苦労したのは、ブロック認識プログラムです。データ上の1つの塊をまとめて処理するのに、この独特のヘックス構造のコマのせいで、前例がないような独創的な処理をいろいろと書かなくてはなりませんでした。

作りたかったけどv1.0にはあきらめた機能 ほか

アルファテスターからの指摘もありましたが、Undoがないのはけっこう辛いです。結局、Undoの実装のためには内部データを改変のたびに時系列順に保存し、保存した最新-1の状態に戻すといった実装になると思います。この、無段階Undoを実装することは可能と思われましたが、割と大掛かりな機能になりそうな(1か月ぐらいかかりそう)気配がしたので初版では見送りました。

本アプリケーションはScriptableではありません。将来的には、書類の読み取りと変更を行う機能を持つScript Libraryを同梱する方向でAppleScript対応を考えています(たぶん、これが一番楽で実用的)。

キャンバスの回転機能は単体で動くものが出来上がっていますが、まだアプリケーションに組み込んで動作させるところまでは行っていません。

「2つのキーワードの共通要素をリストアップする」プログラムはこのKamenokoの部品用に作ったもので、単体ではそれなりに有用な部品ではあるものの、本アプリケーションにどのように組み込むかのいいアイデアが出ませんでした。データとして処理すると有用さがわかるものの、それをどのように可視化するかが課題です(多すぎるアイデアにつぶされない戦い)。

本アプリケーションには検索機能が実装されていません。検索系の部品として、類義語展開したうえで検索を行う「スタークエリー」という部品をAppleScriptで作ってあるので、組み込むとしたらこれだと(指定のキーワードだけでなく、類義語でもヒットする)思っているのですが、英語+日本語の類義語(シソーラス)辞書が200MBぐらいあるのとGUI的にどうやってヒット状況を表示するかのアイデアがなかったので実装を見送りました。あとから考えると200MBぐらい昨今のアプリケーションでは問題ではないレベルなので、悩む必要はなかったようです。

開発中はフォントメニューのキャッシュ機能を有効にしていましたが、リリース版ではこれをオフにしました。Kamenokoを起動していない間にフォントの変更(追加、削除)が行われたことを検出する方法が思いつかなかったので、フォントメニューのキャッシュが危険に思われたためです。フォントパネルを表示させてフォントを指定する方法も試してみたものの、あまりピンとこなかったので使いませんでした。

目下、メインScriptが3,000行を超えるぐらいのサイズで、全体では5,000行ぐらいは行っていると思います。メンテナンス性があまりよくないので、機能追加を行うためにはメイン部分のスリム化が必須な状況でしょう。

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

指定アプリケーションを指定言語環境で再起動

Posted on 4月 30, 2020 by Takaaki Naganoya

指定アプリケーションを、現在のユーザーアカウントで指定可能な言語環境を指定して再起動するAppleScriptです。

Xcodeにこのような機能があり、そのような処理を行える可能性について思い至っていました。shell commandについてはEdama2さんから教えていただきました。あー、やっぱりこういう感じなんですね。

次に、言語コードを求める方法ですが、調べても全言語の言語コードを求める方法が見当たらなかったので(これは、探し方が足りないだけ)、現在のユーザーアカウントで指定可能な言語コードを求める方法に落ち着きました。

本Scriptを実行すると、指定アプリケーションを起動する言語コードを選択。

処理するアプリケーションを選択。choose applicationコマンドが活躍するのはとても珍しいケースです。

英語(English)を指定した場合。

フランス語(French)を指定した場合。

日本語(Japanese)を指定した場合。

個人的には、英語環境でアプリケーションを動かしつつ、執筆用のアプリケーション(Keynote)だけ日本語環境で動かすことができて、些細なコマンドの呼称を確認する必要がなくていい感じです。あれ? 日本語環境でターゲットのアプリケーションだけ英語環境を指定して起動すればいいんじゃ????

AppleScript名:指定アプリケーションを指定言語環境で再起動
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/04/30
–  Special Thanks to : Edama2
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
–  
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

set aLocList to (current application’s NSLocale’s preferredLanguages()) as list

set targLanguage to choose from list aLocList
set anApp to choose application

set apFile to POSIX path of (path to anApp)
tell anApp to quit

set sText to "open -n -a " & quoted form of apFile & " –args -AppleLanguages ’(\"" & targLanguage & "\")’"
do shell script sText

★Click Here to Open This Script 

Posted in Language Locale shell script | Tagged 10.13savvy 10.14savvy 10.15savvy | 3 Comments

アラートダイアログ上にWkWebViewでGoogle Chartsを表示 v2

Posted on 4月 29, 2020 by Takaaki Naganoya

アラートダイアログ上にWkWebViewを配置し、Google Chartsを用いてPie Chartを表示するAppleScriptです。

自分の開発環境(MacBook Pro Retina 2012, Core i7 2.6GHz)で10日間のアクセス履歴を処理して1.38秒程度でダイアログ表示してグラフ描画に入ります。3秒強ぐらいで描画が終了します。

WkWebViewに対して、文字列で組み立てたHTMLを読み込んでグラフ表示しています。Pie Chart上にマウスカーソルを乗せると反応します。一応表示できているぐらいで、デザイン的には余計な余白ができたままで、いまひとつな感じです。せめて、WkWebViewの背景を透明化できると大味な表示をいくらか緩和できるかと思っているのですが、WkWebViewの透明背景にはNSColorではなく(AppleScriptから作成できない)CGColorでclearColor(透明色)を指定する必要があるようで、、、、

サンプル表示データは、Safariの10日間のアクセス履歴からドメイン単位で計算したヒストグラムを、その場で計算したものを使っています。

本Scriptは、①NSAlertのダイアログ表示の経験 ②WkWebView上へのコンテンツ表示の経験 ③グラフ表示用FrameworkやSVGベースのグラフ作成の経験 を経て、2・3年越しで完成したものです。とくに、WkWebViewについてはサンプル数がそれほど多くなく、用途の方向性がObjective-CやSwiftと若干異なるために、参考にできるサンプルの数が多くない状況。必然的に、いろいろ試しては失敗を重ねてきました。急に出来上がってきたものではありません。

Safariの履歴集計ScriptをScriptオブジェクトの中に放り込んだら、scripting additionsの用語をusing terms from句で囲っておく必要がありました。何回か経験していますが、知らないと対処に困る現象です。

現状(macOS 10.14以降)では、Scripting AdditionはmacOS標準搭載のStandard Additionsしか存在していないし認識も行われないため、エラー内容がいまひとつわかりにくく、不正確であるように思えます。Apple純正のStandard Additionsしか存在していないんだから自分で判断しろやコラ、と言いたくなります。

AppleScript名:アラートダイアログ上にWebViewでGoogle Chartを表示 v2.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/03/02
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use framework "WebKit"
use scripting additions

property |NSURL| : a reference to current application’s |NSURL|
property NSAlert : a reference to current application’s NSAlert
property NSString : a reference to current application’s NSString
property NSButton : a reference to current application’s NSButton
property WKWebView : a reference to current application’s WKWebView
property WKUserScript : a reference to current application’s WKUserScript
property NSURLRequest : a reference to current application’s NSURLRequest
property NSRunningApplication : a reference to current application’s NSRunningApplication
property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding
property WKUserContentController : a reference to current application’s WKUserContentController
property WKWebViewConfiguration : a reference to current application’s WKWebViewConfiguration
property WKUserScriptInjectionTimeAtDocumentEnd : a reference to current application’s WKUserScriptInjectionTimeAtDocumentEnd

property returnCode : 0

–Calc Safari access domain from history
set aRes to calcSafariHistoryBest10Domain(10) of safariHistoryLib

set aList to {{"Domain", "Access"}}
repeat with i in aRes
  set aDom to theName of i
  
set accessNum to numberOfTimes of i
  
set the end of aList to {aDom, accessNum}
end repeat

–set aList to {{"Task", "Hours per Day"}, {"Work", 8}, {"Eat", 2}, {"TV", 4}, {"Gym", 2}, {"Sleep", 8}}

set aJsonArrayStr to array2DToJSONArray(aList) of me

–Pie Chart Template HTML
set myStr to "<!DOCTYPE html>
<html lang=\"UTF-8\">
<body>
<div id=\"piechart\"></div>

<script type=\"text/javascript\" src=\"https://www.gstatic.com/charts/loader.js\"></script>

<script type=\"text/javascript\">
// Load google charts
google.charts.load(’current’, {’packages’:[’corechart’]});
google.charts.setOnLoadCallback(drawChart);

// Draw the chart and set the chart values
function drawChart() {
var data = google.visualization.arrayToDataTable(%@);

// Optional; add a title and set the width and height of the chart
var options = {’title’:’’, ’width’:600, ’height’:400};

// Display the chart inside the <div> element with id=\"piechart\"
var chart = new google.visualization.PieChart(document.getElementById(’piechart’));
chart.draw(data, options);
}
</script>

</body>
</html>"

set aString to current application’s NSString’s stringWithFormat_(myStr, aJsonArrayStr) as string

set paramObj to {myMessage:"Pie Chart Test", mySubMessage:"This is a simple pie chart using google charts", htmlStr:aString}
–my browseStrWebContents:paramObj–for debug
my performSelectorOnMainThread:"browseStrWebContents:" withObject:(paramObj) waitUntilDone:true

on browseStrWebContents:paramObj
  set aMainMes to myMessage of paramObj
  
set aSubMes to mySubMessage of paramObj
  
set htmlString to (htmlStr of paramObj)
  
  
set aWidth to 600
  
set aHeight to 450
  
  
–WebViewをつくる
  
set aConf to WKWebViewConfiguration’s alloc()’s init()
  
  
–指定HTML内のJavaScriptをFetch
  
set jsSource to pickUpFromToStr(htmlString, "<script type=\"text/javascript\">", "</script>") of me
  
  
set userScript to WKUserScript’s alloc()’s initWithSource:jsSource injectionTime:(WKUserScriptInjectionTimeAtDocumentEnd) forMainFrameOnly:true
  
set userContentController to WKUserContentController’s alloc()’s init()
  
userContentController’s addUserScript:(userScript)
  
aConf’s setUserContentController:userContentController
  
  
set aWebView to WKWebView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight – 100)) configuration:aConf
  
aWebView’s setNavigationDelegate:me
  
aWebView’s setUIDelegate:me
  
aWebView’s setTranslatesAutoresizingMaskIntoConstraints:true
  
  
set bURL to |NSURL|’s fileURLWithPath:(POSIX path of (path to me))
  
aWebView’s loadHTMLString:htmlString baseURL:(bURL)
  
  
— set up alert  
  
set theAlert to NSAlert’s alloc()’s init()
  
tell theAlert
    its setMessageText:aMainMes
    
its setInformativeText:aSubMes
    
its addButtonWithTitle:"OK"
    
–its addButtonWithTitle:"Cancel"
    
its setAccessoryView:aWebView
    
    
set myWindow to its |window|
  end tell
  
  
— show alert in modal loop
  
NSRunningApplication’s currentApplication()’s activateWithOptions:0
  
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
  
  
–Stop Web View Action
  
set bURL to |NSURL|’s URLWithString:"about:blank"
  
set bReq to NSURLRequest’s requestWithURL:bURL
  
aWebView’s loadRequest:bReq
  
  
if (my returnCode as number) = 1001 then error number -128
end browseStrWebContents:

on doModal:aParam
  set (my returnCode) to (aParam’s runModal()) as number
end doModal:

on viewDidLoad:aNotification
  return true
end viewDidLoad:

on fetchJSSourceString(aURL)
  set jsURL to |NSURL|’s URLWithString:aURL
  
set jsSourceString to NSString’s stringWithContentsOfURL:jsURL encoding:(NSUTF8StringEncoding) |error|:(missing value)
  
return jsSourceString
end fetchJSSourceString

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

–リストを任意のデリミタ付きでテキストに
on retArrowText(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 retArrowText

on array2DToJSONArray(aList)
  set anArray to current application’s NSMutableArray’s arrayWithArray:aList
  
set jsonData to current application’s NSJSONSerialization’s dataWithJSONObject:anArray options:(0 as integer) |error|:(missing value) –0 is
  
set resString to current application’s NSString’s alloc()’s initWithData:jsonData encoding:(current application’s NSUTF8StringEncoding)
  
return resString
end array2DToJSONArray

–Safariのn日前からの履歴をドメイン別に集計してソート
script safariHistoryLib
  use scripting additions
  
use framework "Foundation"
  
property parent : AppleScript
  
  
property |NSURL| : a reference to current application’s |NSURL|
  
  
script spd
    property sList : {}
    
property nList : {}
    
property sRes : {}
  end script
  
  
  
on calcSafariHistoryBest10Domain(daysBefore)
    –現在日時のn日前を求める
    
using terms from scripting additions
      set origDate to (current date) – (daysBefore * days)
    end using terms from
    
set dStr to convDateObjToStrWithFormat(origDate, "yyyy-MM-dd hh:mm:ss") of me
    
    
set aDBpath to "~/Library/Safari/History.db"
    
set pathString to current application’s NSString’s stringWithString:aDBpath
    
set newPath to pathString’s stringByExpandingTildeInPath()
    
    
set aText to "sqlite3 " & newPath & " ’SELECT datetime(history_visits.visit_time+978307200, \"unixepoch\", \"localtime\"), history_visits.title || \" @ \" || substr(history_items.URL,1,max(length(history_items.URL)*(instr(history_items.URL,\" & \")=0),instr(history_items.URL,\" & \"))) as Info FROM history_visits INNER JOIN history_items ON history_items.id = history_visits.history_item where history_visits.visit_time>(julianday(\"" & dStr & "\")*86400-211845068000) ORDER BY visit_time ASC LIMIT 999999;’"
    
    
using terms from scripting additions
      set (sRes of spd) to do shell script aText
    end using terms from
    
    
set (sList of spd) to (paragraphs of (sRes of spd))
    
    
set (nList of spd) to {}
    
    
repeat with i in (sList of spd)
      set j to contents of i
      
      
–Parse each field
      
set j2 to parseByDelim(j, {"|", "@ "}) of me
      
      
–Calculate URL’s domain only
      
set j3 to contents of last item of j2
      
set aURL to (|NSURL|’s URLWithString:j3)
      
      
if aURL = missing value then
        set j4 to ""
      else
        set j4 to (aURL’s |host|()) as string
      end if
      
      
set the end of (nList of spd) to j4
    end repeat
    
    
–登場頻度でURLを集計
    
set aList to countItemsByItsAppearance((nList of spd)) of me
    
    
    
–Best 10の計算のために10位以下をまとめる
    
set best9 to items 1 thru 9 of aList
    
set best10 to items 10 thru -1 of aList
    
    
set otherTimes to 0
    
repeat with i in best10
      set otherTimes to otherTimes + (numberOfTimes of i)
    end repeat
    
    
set the end of best9 to {theName:"Other", numberOfTimes:otherTimes}
    
return best9
  end calcSafariHistoryBest10Domain
  
  
  
  
on parseByDelim(aData, aDelim)
    set curDelim to AppleScript’s text item delimiters
    
set AppleScript’s text item delimiters to aDelim
    
set dList to text items of aData
    
set AppleScript’s text item delimiters to curDelim
    
return dList
  end parseByDelim
  
  
  
–出現回数で集計
  
on countItemsByItsAppearance(aList)
    set aSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList
    
set bArray to current application’s NSMutableArray’s array()
    
set theEnumerator to aSet’s objectEnumerator()
    
    
repeat
      set aValue to theEnumerator’s nextObject()
      
if aValue is missing value then exit repeat
      
bArray’s addObject:(current application’s NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{"theName", "numberOfTimes"})
    end repeat
    
    
–出現回数(numberOfTimes)で降順ソート
    
set theDesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:"numberOfTimes" ascending:false
    
bArray’s sortUsingDescriptors:{theDesc}
    
    
return bArray as list
  end countItemsByItsAppearance
  
  
  
on convDateObjToStrWithFormat(aDateO as date, aFormatStr as string)
    set aDF to current application’s NSDateFormatter’s alloc()’s init()
    
    
set aLoc to current application’s NSLocale’s currentLocale()
    
set aLocStr to (aLoc’s localeIdentifier()) as string
    
    
aDF’s setLocale:(current application’s NSLocale’s alloc()’s initWithLocaleIdentifier:aLocStr)
    
aDF’s setDateFormat:aFormatStr
    
set dRes to (aDF’s stringFromDate:aDateO) as string
    
return dRes
  end convDateObjToStrWithFormat
  
end script

★Click Here to Open This Script 

Posted in dialog Web Contents Control | Tagged 10.13savvy 10.14savvy 10.15savvy NSAlert NSButton NSRunningApplication NSString NSURL NSURLRequest NSUTF8StringEncoding Safari WKUserContentController WKUserScript WKUserScriptInjectionTimeAtDocumentEnd WKWebView WKWebViewConfiguration | 1 Comment

Safariの履歴を読み込んでBest 10を求める。「その他」計算機能つき

Posted on 4月 29, 2020 by Takaaki Naganoya

Safariの閲覧履歴のdatabaseにアクセスして、domain単位でベスト10を求めるAppleScriptです。

自分の開発環境(MacBook Pro Retina 2012, Core i7 2.6GHz)で10日間のアクセス履歴を処理して0.8秒程度です。

以前のSafariではplistでヒストリを管理していましたが、気づいたらSqliteのDBで管理するように変わっていたので(Safari 10あたりで?)、よろしく抽出して加工してみました。おそらく、最低限の情報のみ抽出することで現状の半分ぐらいの処理時間で処理できるようになるとは思うのですが、汎用性を持たせるために現状のレベルにまとめています。

計算結果が当たり前すぎて予想よりはるかに面白くなかったので、そのことに逆に驚きました。

AppleScript名:Safariの履歴を読み込んでBest 10を求める。「その他」計算機能つき.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/04/29
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.7" — (10.13) or later
use scripting additions
use framework "Foundation"

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

script spd
  property sList : {}
  
property nList : {}
  
property sRes : {}
end script

set aRes to calcSafariHistoryBest10Domain(10) of me
–> {{theName:"piyocast.com", numberOfTimes:1100}, {theName:"www.youtube.com", numberOfTimes:710}, {theName:"twitter.com", numberOfTimes:354}, {theName:"www.google.com", numberOfTimes:331}, {theName:"syosetu.com", numberOfTimes:199}, {theName:"github.com", numberOfTimes:140}, {theName:"developer.apple.com", numberOfTimes:139}, {theName:"appstoreconnect.apple.com", numberOfTimes:121}, {theName:"xxxxxxxxxxxxx", numberOfTimes:106}, {theName:"Other", numberOfTimes:847}}

on calcSafariHistoryBest10Domain(daysBefore)
  –現在日時のn日前を求める
  
set origDate to (current date) – (daysBefore * days)
  
set dStr to convDateObjToStrWithFormat(origDate, "yyyy-MM-dd hh:mm:ss") of me
  
  
set aDBpath to "~/Library/Safari/History.db"
  
set pathString to current application’s NSString’s stringWithString:aDBpath
  
set newPath to pathString’s stringByExpandingTildeInPath()
  
  
set aText to "sqlite3 " & newPath & " ’SELECT datetime(history_visits.visit_time+978307200, \"unixepoch\", \"localtime\"), history_visits.title || \" @ \" || substr(history_items.URL,1,max(length(history_items.URL)*(instr(history_items.URL,\" & \")=0),instr(history_items.URL,\" & \"))) as Info FROM history_visits INNER JOIN history_items ON history_items.id = history_visits.history_item where history_visits.visit_time>(julianday(\"" & dStr & "\")*86400-211845068000) ORDER BY visit_time ASC LIMIT 999999;’"
  
set (sRes of spd) to do shell script aText
  
  
set (sList of spd) to (paragraphs of (sRes of spd))
  
  
set (nList of spd) to {}
  
  
repeat with i in (sList of spd)
    set j to contents of i
    
    
–Parse each field
    
set j2 to parseByDelim(j, {"|", "@ "}) of me
    
    
–Calculate URL’s domain only
    
set j3 to contents of last item of j2
    
set aURL to (|NSURL|’s URLWithString:j3)
    
    
if aURL = missing value then
      set j4 to ""
    else
      set j4 to (aURL’s |host|()) as string
    end if
    
    
set the end of (nList of spd) to j4
  end repeat
  
  
–登場頻度でURLを集計
  
set aList to countItemsByItsAppearance((nList of spd)) of me
  
  
  
–Best 10の計算のために10位以下をまとめる
  
set best9 to items 1 thru 9 of aList
  
set best10 to items 10 thru -1 of aList
  
  
set otherTimes to 0
  
repeat with i in best10
    set otherTimes to otherTimes + (numberOfTimes of i)
  end repeat
  
  
set the end of best9 to {theName:"Other", numberOfTimes:otherTimes}
  
return best9
end calcSafariHistoryBest10Domain

on parseByDelim(aData, aDelim)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to aDelim
  
set dList to text items of aData
  
set AppleScript’s text item delimiters to curDelim
  
return dList
end parseByDelim

–出現回数で集計
on countItemsByItsAppearance(aList)
  set aSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList
  
set bArray to current application’s NSMutableArray’s array()
  
set theEnumerator to aSet’s objectEnumerator()
  
  
repeat
    set aValue to theEnumerator’s nextObject()
    
if aValue is missing value then exit repeat
    
bArray’s addObject:(current application’s NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{"theName", "numberOfTimes"})
  end repeat
  
  
–出現回数(numberOfTimes)で降順ソート
  
set theDesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:"numberOfTimes" ascending:false
  
bArray’s sortUsingDescriptors:{theDesc}
  
  
return bArray as list
end countItemsByItsAppearance

on convDateObjToStrWithFormat(aDateO as date, aFormatStr as string)
  set aDF to current application’s NSDateFormatter’s alloc()’s init()
  
  
set aLoc to current application’s NSLocale’s currentLocale()
  
set aLocStr to (aLoc’s localeIdentifier()) as string
  
  
aDF’s setLocale:(current application’s NSLocale’s alloc()’s initWithLocaleIdentifier:aLocStr)
  
aDF’s setDateFormat:aFormatStr
  
set dRes to (aDF’s stringFromDate:aDateO) as string
  
return dRes
end convDateObjToStrWithFormat

★Click Here to Open This Script 

Posted in shell script | Tagged 10.13savvy 10.14savvy 10.15savvy | Leave a comment

Previewで現在表示中のPDFのページ番号を抽出する

Posted on 4月 29, 2020 by Takaaki Naganoya

macOS標準搭載の画像/PDFビューワーの「Preview.app」で表示中のPDFの、現在表示中のページの番号を取得するAppleScriptです。

本来、Preview.appのような超低機能アプリケーションから強引に情報を(GUI Scriptingまで使って)取得する意味はありません。PDFビューワーとしてまっとうな機能を持っているSkimを使って表示中のページ番号を取得するのが筋です。

ただ、どうしてもPreviewでないといけないケースで、仕方なく作ったものですが、英語環境でも日本語環境でも同様に動くために作ってみたらこんな感じに。指定アプリケーション単体で言語環境を指定して起動できると、各言語環境における動作確認が手軽に行えてよいと思うものの、手段がありそうで見つかりません(Xcode上でそういう起動ができるので、不可能ではないと思うのですが)。


▲英語環境で実行したところ(macOS 10.14.6)


▲日本語環境で実行したところ(macOS 10.15.4)

仕方なくGUI Scripting経由でウィンドウのタイトルを取得して、ファイル名とページ情報を文字列処理で分離しています。このあたり、英語環境と日本語環境でセパレータ(括弧)が異なるので、分離したページ情報から数字判定を行なって取得しています。Preview.appのアプリケーションバンドル内にこうしたフォーマットのテキストが存在していれば、そちらを使うべきです(見つかっていないので現状こんな感じで)。

GUI Scripting内でプロセス名を指定する箇所で、ローカライズされたプロセス名をCocoaの機能を用いて取得しています。これで、英語環境と日本語環境については問題なく共通Scriptでカバーできています。

AppleScript名:Previewで現在表示中のPDFのページ番号を抽出する.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/04/29
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

set pNum to retPreviewDispPageNumber() of me

on retPreviewDispPageNumber()
  set aLocName to getLocalizedName("com.apple.Preview") of me
  
  
tell application "Preview"
    if (count every document) = 0 then return false
  end tell
  
  
tell application "System Events"
    tell process aLocName
      tell window 1
        set aTitle to title
      end tell
    end tell
  end tell
  
  
set aPageInfo to pickUpFromToStr(aTitle, "(", ")") of me –English env
  
if aPageInfo = false then
    set aPageInfo to pickUpFromToStr(aTitle, "(", ")") of me –double witdh parenthesis (Japanese env)
  end if
  
set pList to words of aPageInfo
  
set hitF to false
  
repeat with i in pList
    set nRes to chkNumeric(i) of me
    
if nRes = true then
      set hitF to true
      
exit repeat
    end if
  end repeat
  
  
if hitF = false then return
  
return i as integer
end retPreviewDispPageNumber

on getLocalizedName(aBundleID as string)
  set pRes to getProcessByBUndleID(aBundleID) of me
  
if pRes = false then return ""
  
set pName to pRes’s localizedName()
  
return pName as string
end getLocalizedName

–指定プロセスを取得する
on getProcessByBUndleID(aBundleID)
  set appArray to current application’s NSRunningApplication’s runningApplicationsWithBundleIdentifier:aBundleID
  
if appArray’s |count|() > 0 then
    set appItem to appArray’s objectAtIndex:0
    
return appItem
  else
    return false
  end if
end getProcessByBUndleID

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

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

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

★Click Here to Open This Script 

Posted in GUI Scripting PDF Text | Tagged 10.13savvy 10.14savvy 10.15savvy NSCharacterSet NSRunningApplication NSScanner Preview | Leave a comment

システム環境設定の「ディスプレイ」>「ディスプレイ」を表示

Posted on 4月 28, 2020 by Takaaki Naganoya

システム環境設定の「ディスプレイ」paneの「ディスプレイ」を表示するAppleScriptです。

やりかたは山のようにあるものの、Cocoa系の機能を使うとこんな感じ。

AppleScript名:システム環境設定の「ディスプレイ」>「ディスプレイ」を表示_asobjc.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/04/28
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

current application’s NSWorkspace’s sharedWorkspace()’s openFile:"/System/Library/PreferencePanes/Displays.prefPane"

★Click Here to Open This Script 

まんま、同じ内容をshell呼び出しで書くとこんな感じ。

AppleScript名:システム環境設定の「ディスプレイ」>「ディスプレイ」を表示_shell.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/04/28
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

do shell script "open /System/Library/PreferencePanes/Displays.prefPane"

★Click Here to Open This Script 

System Events経由でファイルオープンするとこんな感じ。POSIX pathをfileとして指定できて驚きました。aliasにcastしないとopenできないかと思っていました。

AppleScript名:システム環境設定の「ディスプレイ」>「ディスプレイ」を表示_System Events.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/04/28
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—

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

tell application "System Events"
  open file "/System/Library/PreferencePanes/Displays.prefPane"
end tell

★Click Here to Open This Script 

AppleScript的にいろいろルーチンを整備して汎用性を持たせつつ、十分な機能を用意するとこんな感じでしょうか。

AppleScript名:システム環境設定の「ディスプレイ」>「ディスプレイ」を表示
— Created 2017-10-10 by Takaaki Naganoya
— Created 2020-04-28 by Takaaki Naganoya
— 2020 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

–Get every pane ID
set aList to getEveryPaneID() of me

–Get every anchor in a pane
set pList to getEveryAnchorName("com.apple.preference.displays") of me
–> {"displaysArrangementTab", "displaysNightShiftTab", "displaysColorTab", "displaysGeometryTab", "displaysDisplayTab"}

set aRes to dispSystemPreferences("com.apple.preference.displays", "displaysDisplayTab") of me
–> true

on dispSystemPreferences(paneID, anchorID)
  tell application "System Preferences"
    activate
    
set pList to id of every pane
    
if paneID is not in pList then return false
    
    
set current pane to pane paneID
    
tell current pane
      set nList to name of every anchor
      
if anchorID is not in nList then return false
      
reveal anchor anchorID
    end tell
  end tell
  
  
return true
end dispSystemPreferences

on getEveryPaneID()
  tell application "System Preferences"
    return id of every pane
  end tell
end getEveryPaneID

on getEveryAnchorName(paneID)
  tell application "System Preferences"
    set pList to id of every pane
    
if paneID is not in pList then return false
    
set current pane to pane paneID
    
tell current pane
      return name of every anchor
    end tell
  end tell
end getEveryAnchorName

★Click Here to Open This Script 

Posted in System | Tagged 10.13savvy 10.14savvy 10.15savvy NSWorkspace System Preferences | Leave a comment

2D Listの各要素を逆順に

Posted on 4月 26, 2020 by Takaaki Naganoya

2D Listの各要素を逆順に入れ替えるAppleScriptです。

そのままreverse ofで逆順にすると、

set aList to {{1}, {2, 3, 4, 5, 6, 7}, {3, 4, 5, 6, 7, 8, 9}}
set bList to reverse of aList
--> {{3, 4, 5, 6, 7, 8, 9}, {2, 3, 4, 5, 6, 7}, {1}}

のようになりますが、これでは目的にかないませんでした。

ちょうど、Kamenokoのセル回転テーブルを反対方向に回転させたかったので、

--> {{1}, {7, 6, 5, 4, 3, 2}, {9, 8, 7, 6, 5, 4, 3}}

のような結果が欲しかったのでした。本ルーチンを実際に組み込んで、逆方向へのデータ回転を実現させました。

ただ、データ上で回転できているだけで視覚効果については別問題です。プレビュー画像を作成しにいくとメモリ上にゴミが残ったまま消えないとか、あんまり視覚効果を利用しにくい雰囲気がしていますけれども。

AppleScript名:2D Listの各要素を逆順に.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/04/26
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set aList to {{1}, {2, 3, 4, 5, 6, 7}, {3, 4, 5, 6, 7, 8, 9}}
set bList to reverse2DListEachItems(aList) of me
–> {{1}, {7, 6, 5, 4, 3, 2}, {9, 8, 7, 6, 5, 4, 3}}

on reverse2DListEachItems(aList)
  set newList to {}
  
repeat with i in aList
    set j to contents of i
    
set tmpJ to reverse of j
    
set the end of newList to tmpJ
  end repeat
  
  
return newList
end reverse2DListEachItems

★Click Here to Open This Script 

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

Double PDF v2.1準備中

Posted on 4月 24, 2020 by Takaaki Naganoya

Double PDF v2.1をMac App Storeに出すべく準備中です。このバージョンは、あくまでアプリケーションの署名周りの問題を解決するだけのリリースであり、機能的な追加を行うものではありません。

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

ディスプレイのミラーリング表示(sandbox対応)

Posted on 4月 23, 2020 by Takaaki Naganoya

Mac用のオープンソースのディスプレイミラーリング・ツール「mirror-displays」を改変して、Xcode上でコードサインしやすく、かつAppleScriptアプリケーション(Xcode上で記述)から呼び出しやすくしたものです。

ディスプレイのミラーリング表示のOn/Offを行うmirror-displaysを、そのままMac App Storeに申請するアプリケーションの中にバイナリで入れようとしたら、Xcode上のValidate(Mac App Storeにアップロードする前段階の各種妥当性チェック)でひっかかってしまいました。

アプリケーションバンドル中のResourcesフォルダに入れてdo shell scriptで呼ぶという「お気楽」な呼び方が(Code Signの問題で)できなかったわけです。

# コマンドライン・ツールとしてビルドするときにCode Signすればよかったんじゃないか、という話もありますが、いずれ最終的にこの形式にする必要があったので、これでいいんじゃないかと

そこで、コマンドラインから呼び出す形式ではなく、Objective-Cのプログラム「らしい」形式に変更して(ヘッダファイルをゼロから書き起こしました)、AppleScriptから呼び出しやすく変更してみました。配布条件がGPLだったので、ここにmirror-displayまわりのソースと最低限の呼び出し側のAppleScriptアプリケーションのプロジェクトを掲載した次第です。

–> Download Xcode Project’s zip-archive

AppleScript名:AppDelegate.applescript
—
— AppDelegate.applescript
— mirrorTest
—
— Created by Takaaki Naganoya on 2020/04/15.
— Copyright © 2020 Takaaki Naganoya. All rights reserved.
—

script AppDelegate
  property parent : class "NSObject"
  
  
— IBOutlets
  
property theWindow : missing value
  
  
on applicationWillFinishLaunching:aNotification
    — Insert code here to initialize your application before any files are opened
  end applicationWillFinishLaunching:
  
  
on applicationShouldTerminate:sender
    — Insert code here to do any housekeeping before your application quits
    
return current application’s NSTerminateNow
  end applicationShouldTerminate:
  
  
on clicked:sender
    current application’s mirrorObjC’s alloc()’s init()’s mirror()
  end clicked:
end script

★Click Here to Open This Script 

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

Post navigation

  • Older posts
  • Newer posts

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

Google Search

Popular posts

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

Tags

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

カテゴリー

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

アーカイブ

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

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

メタ情報

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

Forum Posts

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

メタ情報

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