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

指定アプリケーションの指定言語のstringsファイルの内容をすべて取り出す

Posted on 9月 21, 2019 by Takaaki Naganoya

バンドルIDで指定したアプリケーションのResourcesフォルダ中の、指定ロケールのstringsファイルをすべて読み込んでkeyを取り出すAppleScriptです。

アプリケーション内の指定のローカライズしたメッセージ(テキスト)の内容を取り出すことはできますが、そのためにはキーを知っておく必要があります。そのキーを取り出してローカライズされた文字列を取り出すため、キーを調査してみました。

これをそのまま何かのツールなりScriptに使うというものではなく、いわゆる「下調べ」のためのScriptの部品です。

ほぼ、ありもののルーチンを再利用しただけのプログラムでできていますが、ありものはありもので、数千本のAppleScriptのストックからそれを探し出してくるのも一苦労です。

アプリケーションバンドル内のResourcesフォルダ以下の(各lprojフォルダ以下の)stringsファイルの中身はまんま(シリアライズした)NSDictionaryなので、そのままDictionaryに読み込んでallkey()などのメソッドを実行できます。昔のstringsファイルはテキストファイルだったような気がしますが、テキストファイルだとparseしないといけないんで、ビルド時にparseしておいてDictionaryの状態でファイルに書いておくのは正しいと思います。

Xcode 8あたりから、アプリケーションのローカライズのルールが変更になったようで、基本となる言語環境がBase.lprojになり、英語はen.lprojといった1ローカライズ言語という位置付けに変更になりました。

NSLocalizedStringFromTableInBundleを使ってアクセスしようかとも思ったのですが、こちらはまだ目的を達成できていません。


▲Xcode 11上で実験的に作成したAppleScriptアプリケーションのバンドル構造(左)。ローカライズしていない状態だとEnglishではなくBase.lprojが作成される。右はKeynote.app/Contents/Resources/ja.lprojフォルダの内容。stringsファイルが大量に存在している

AppleScript名:指定アプリケーションの指定言語のstringsファイルの内容をすべて取り出す.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/09/21
—
–  Copyright © 2019 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 NSArray : a reference to current application’s NSArray
property NSBundle : a reference to current application’s NSBundle
property NSPredicate : a reference to current application’s NSPredicate
property NSDictionary : a reference to current application’s NSDictionary
property NSWorkspace : a reference to current application’s NSWorkspace
property NSFileManager : a reference to current application’s NSFileManager
property NSMutableDictionary : a reference to current application’s NSMutableDictionary
property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey
property NSDirectoryEnumerationSkipsHiddenFiles : a reference to current application’s NSDirectoryEnumerationSkipsHiddenFiles
property NSDirectoryEnumerationSkipsPackageDescendants : a reference to current application’s NSDirectoryEnumerationSkipsPackageDescendants

set targID to "com.apple.iWork.Keynote"

set bRes to getLocalizationsFromBundleID(targID) of me
–>  {"de", "he", "en_AU", "ar", "el", "ja", "en", "uk", "es_419", "zh_CN", "es", "da", "it", "sk", "pt_PT", "ms", "sv", "cs", "ko", "Base", "no", "hu", "zh_HK", "tr", "pl", "zh_TW", "en_GB", "vi", "ru", "fr_CA", "fr", "fi", "id", "nl", "th", "pt", "ro", "hr", "hi", "ca"}

set curLang to first item of (choose from list bRes)
set aPath to retPathFromBundleID(targID) of me

set aPath to aPath & "/Contents/Resources/" & curLang & ".lproj"
set sList to getFilepathListByUTI(aPath, "com.apple.xcode.strings-text", "POSIX") of me

set aMDict to NSMutableDictionary’s new()

repeat with i in sList
  set j to contents of i
  
set aDict to (NSDictionary’s alloc()’s initWithContentsOfFile:j)
  (
aMDict’s addEntriesFromDictionary:aDict)
end repeat

return aMDict’s allKeys() as list
–> {"Interactive Bubble Chart", "Rehearse Slideshow", "PMT_ARGUMENT_1", "ACCRINTM_ARGUMENT_4_MODE_0", "Truck_378",….}

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

on getFilepathListByUTI(aFolPOSIX, aUTI as string, aFileType as string)
  script spdFile
    property urlList : {}
  end script
  
  
if aFileType is not in {"file", "POSIX"} then return {}
  
  
set aFM to NSFileManager’s defaultManager()
  
set aFolExt to (aFM’s fileExistsAtPath:aFolPOSIX isDirectory:true) as boolean
  
if aFolExt = false then return {} –フォルダ自体が存在しなければヌルリストを返す
  
  
set aURL to |NSURL|’s fileURLWithPath:aFolPOSIX
  
set theOptions to ((NSDirectoryEnumerationSkipsPackageDescendants) as integer) + ((NSDirectoryEnumerationSkipsHiddenFiles) as integer)
  
set urlArray to (aFM’s contentsOfDirectoryAtURL:aURL includingPropertiesForKeys:{} options:theOptions |error|:(missing value))
  
if urlArray = missing value then return {}
  
  
set (urlList of spdFile) to urlArray as list
  
set newList to {}
  
  
repeat with i in (urlList of spdFile)
    set j to POSIX path of i
    
set tmpUTI to my retUTIfromPath(j)
    
set utiRes to my filterUTIList({tmpUTI}, aUTI)
    
    
if utiRes is not equal to {} then
      if aFileType = "POSIX" then
        set the end of newList to j
      else if aFileType = "file" then
        set the end of newList to POSIX file j
      end if
    end if
    
  end repeat
  
  
return newList
end getFilepathListByUTI

–指定のPOSIX pathのファイルのUTIを求める
on retUTIfromPath(aPOSIXPath)
  set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath
  
set {theResult, theValue} to aURL’s getResourceValue:(reference) forKey:NSURLTypeIdentifierKey |error|:(missing value)
  
  
if theResult = true then
    return theValue as string
  else
    return theResult
  end if
end retUTIfromPath

–UTIリストが指定UTIに含まれているかどうか演算を行う
on filterUTIList(aUTIList, aUTIstr)
  set anArray to NSArray’s arrayWithArray:aUTIList
  
set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr)
  
set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list
  
return bRes
end filterUTIList

★Click Here to Open This Script 

Posted in file Record URL UTI | Tagged 10.12savvy 10.13savvy 10.14savvy NSArray NSBundle NSDictionary NSDirectoryEnumerationSkipsHiddenFiles NSDirectoryEnumerationSkipsPackageDescendants NSFileManager NSMutableDictionary NSPredicate NSURL NSURLTypeIdentifierKey NSWorkspace | Leave a comment

コンテンツ中の表示中のエリア座標を取得する

Posted on 9月 18, 2019 by Takaaki Naganoya

Safariで表示中のWebコンテンツの表示範囲の座標を取得するAppleScriptです。

Webブラウザに対するAppleScriptの処理といえば、

 (1)表示中のURLを取得して処理
 (2)表示中のコンテンツにJavaScriptを実行したりGUI Scripting経由で操作(特定要素をカウントしたりFormに値を入れたりボタンを押したり)
 (3)表示中のHTMLソースを取得して処理
 (4)Webブラウザそのものの環境情報(Bookmarkや履歴など)にアクセスして処理
 (5)選択中のテキストを取得して処理
 (6)テキストを選択しておいて、その内容が該当する要素を抽出

といった操作を行ってきました。

(1)は、Webブラウザで表示中のURLを他のプログラムで処理する場合などに便利な、基礎的な処理です。
(2)は、ロボット的なScriptにありがちな、メニューの奥深く(URLで一発オープンが無理なログインを要求される構造のWebサイトとか)にあるデータを定期的に取得するような処理によく使います。
(3)は、(1)の延長線上にあるもので、HTMLReaderなどのHTMLそのものを解釈して処理できる高機能フレームワークと組み合わせてWebスクレイピングを行うものです
(4)は、書いてあるとおりブックマークや履歴などにアクセスして統計処理を行なったりしています。
(5)は、ちょっとした調べ物や翻訳などを行いたい場合に使っています。
(6)は、(3)の処理を行いたいが、処理対象の要素(表など)が複数あるので、どの要素なのか特定するための補助情報としてテキスト選択を要求するものです。

このうち、(6)に該当する処理が現状だといまひとつです。Webブラウザ上でテキストを選択しておく必要があるというのでは使い勝手がよくありません。

Webコンテンツのうち、Webブラウザ上で表示中の要素を取得するようなやり方であれば、その方が使い勝手がよいことでしょう。Wikipedia上の表データを使いまわしたいが、対象ページ上に表が複数あるので、いま現在Webブラウザのウィンドウ上で見えている範囲内に存在する表を取り出すようにすれば、より気の利いた処理になることでしょう。

AppleScript名:コンテンツ中の表示中のエリア座標を取得する
–https://stackoverflow.com/questions/9271747/can-i-detect-the-user-viewable-area-on-the-browser
tell application "Safari"
  set dCount to count every document
  
if dCount = 0 then return
  
  
set aHeight to do JavaScript "window.innerHeight;" in front document
  
set sHeight to do JavaScript "window.scrollY;" in front document
  
  
set aWidth to do JavaScript "window.innerWidth;" in front document
  
set sWidth to do JavaScript "window.scrollX;" in front document
  
  
return {myWidth:aWidth, scrollX:sWidth, myHeight:aHeight, scrollY:sHeight}
end tell

★Click Here to Open This Script 

Posted in JavaScript Web Contents Control | Tagged 10.12savvy 10.13savvy 10.14savvy Safari | Leave a comment

MacDownのopenコマンドで.mdファイルをオープンできない問題

Posted on 9月 18, 2019 by Takaaki Naganoya

メイン環境をmacOS 10.14に移行してみたら、MarkdownエディタのMacDownがopenコマンドでファイルをオープンできなくなっていました。かなり困ります。

ただ、この問題には思い当たる節がありました。MacDownのopenコマンドは仕様がおかしく、「バグっぽい実装でたまたま動いていたものが、OS側の動作が変わって動かなくなった」ものと推測。

MacDownのopenコマンドはfileのlistを要求してくるので、わざわざ、

set aFile to choose file of type {"net.daringfireball.markdown"}

tell application "MacDown"
	open {aFile}
end tell

のような記述が求められました。アプリケーション側の実装に合わせて書くのがScripterなので、仕方なくこういう記述をしてきましたが、納得はしていませんでした。

MacDownのsdefファイルを調べてみたところ、openコマンドのパラメータにlist=”yes”の記述があったので、これを削除。

<command name="open" code="aevtodoc" description="Open a document.">
 <direct-parameter description="The file to be opened.">
  <type type="file"/>
 </direct-parameter>
</command>

のように手元のMacDownのsdefの内容を書き換えてみたら、

set aFile to choose file of type {"net.daringfireball.markdown"}

tell application "MacDown"
	open aFile
end tell

リストで渡さないように書くと、macOS 10.14上でも問題なくAppleScriptから.mdファイルのオープンを実行できるようになりました。

Posted in Bug Markdown | Tagged 10.14savvy MacDown | Leave a comment

アラートダイアログ上にTab View+Popup Buttonを表示して切り替え

Posted on 9月 16, 2019 by Takaaki Naganoya

アラートダイアログ上にTabViewとPopup Buttonを表示して、Popup Menuの選択状況に合わせてTabViewの表示ビューを切り替え、Popup Menuの選択アイテムを1はじまりの番号で返すAppleScriptです。

最終的には各TabViewItem内にCustomViewを生成して、各種データ(TableとかWebとかImageとか)を一覧から選択するようなUI部品として使い回すつもりです。

このバージョンではTabViewのタブが表示状態になっていますが、最終的にはタブレスのTabViewとして表示することになります。

AppleScript名:アラートダイアログ上にTab View+Popup Buttonを表示して切り替え
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/09/16
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSView : a reference to current application’s NSView
property NSAlert : a reference to current application’s NSAlert
property NSMenu : a reference to current application’s NSMenu
property NSTabView : a reference to current application’s NSTabView
property NSMenuItem : a reference to current application’s NSMenuItem
property NSTabViewItem : a reference to current application’s NSTabViewItem
property NSPopUpButton : a reference to current application’s NSPopUpButton
property NSRunningApplication : a reference to current application’s NSRunningApplication

property TabPosition : 0 —0=Top, 1=Left, 2=Bottom, 3=Right, 4=None

property returnCode : 0

property aTabV : missing value
property selectedNum : 1

set paramObj to {myMessage:"Main Message", mySubMessage:"Sub information", viewWidth:500, viewHeight:300}

–my dispTextViewWithAlertdialog:paramObj –for debug
my performSelectorOnMainThread:"dispTabViewWithAlertdialog:" withObject:paramObj waitUntilDone:true
return selectedNum

on dispTabViewWithAlertdialog:paramObj
  –Receive Parameters
  
set aMainMes to (myMessage of paramObj) as string –Main Message
  
set aSubMes to (mySubMessage of paramObj) as string –Sub Message
  
set aWidth to (viewWidth of paramObj) as integer –TextView width
  
set aHeight to (viewHeight of paramObj) as integer –TextView height
  
  
  
set selectedNum to 0
  
  
set aView to NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight))
  
  
–Ppopup Buttonをつくる
  
set a1Button to NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, aHeight – 20, 400, 20)) pullsDown:false
  
a1Button’s removeAllItems()
  
  
set a1Menu to NSMenu’s alloc()’s init()
  
  
repeat with i from 1 to 8
    set aTitle to "Selection #" & (i as string)
    
set aMenuItem to (NSMenuItem’s alloc()’s initWithTitle:aTitle action:"actionHandler:" keyEquivalent:"")
    (
aMenuItem’s setEnabled:true)
    (
aMenuItem’s setTarget:me)
    (
aMenuItem’s setTag:(i as string))
    (
a1Menu’s addItem:aMenuItem)
  end repeat
  
  
a1Button’s setMenu:a1Menu
  
  
–Make Tab View
  
set aTabV to NSTabView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight – 30))
  
aTabV’s setTabViewType:(TabPosition)
  
aTabV’s setTabViewType:(TabPosition)
  
  
repeat with i from 1 to 8
    set aTVItem to (NSTabViewItem’s alloc()’s initWithIdentifier:(i as string))
    (
aTVItem’s setLabel:(i as string))
    
    
–make custom view within a tab view item here
    
    (
aTabV’s addTabViewItem:aTVItem)
  end repeat
  
  
  
aView’s setSubviews:{a1Button, aTabV}
  
aView’s setNeedsDisplay:true
  
  
  
— set up alert
  
set theAlert to NSAlert’s alloc()’s init()
  
tell theAlert
    –for Messages
    
its setMessageText:(aMainMes)
    
its setInformativeText:(aSubMes)
    
    
–for Buttons
    
its addButtonWithTitle:"OK"
    
its addButtonWithTitle:"Cancel"
    
    
–Add Accessory View
    
its setAccessoryView:(aView)
    
    
–for Help Button
    
its setShowsHelp:(true)
    
its setDelegate:(me)
  end tell
  
  
  
— show alert in modal loop
  
NSRunningApplication’s currentApplication()’s activateWithOptions:0
  
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
  
if (my returnCode as number) = 1001 then error number -128
  
  
set selectedNum to (a1Button’s indexOfSelectedItem()) + 1
end dispTabViewWithAlertdialog:

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

on alertShowHelp:aNotification
  display dialog "Help Me!" buttons {"OK"} default button 1 with icon 1
  
return false –trueを返すと親ウィンドウ(アラートダイアログ)がクローズする
end alertShowHelp:

–Popup Action Handler
on actionHandler:sender
  set aTag to tag of sender as integer
  
aTabV’s selectTabViewItemAtIndex:(aTag – 1)
end actionHandler:

★Click Here to Open This Script 

Posted in dialog GUI Menu | Tagged 10.12savvy 10.13savvy 10.14savvy NSAlert NSMenu NSMenuItem NSPopUpButton NSRunningApplication NSTabView NSTabViewItem NSView | Leave a comment

Skimでオープン中のPDFで選択中のテキストを返す

Posted on 9月 16, 2019 by Takaaki Naganoya

フリーでScriptableなmacOS用PDFビューワー「Skim」上でオープン中のPDFで、選択中のテキストの内容を取得するAppleScriptです。

フリーかつオープンソースで提供されているアプリケーションのうち、奇跡的に豊富なAppleScript対応機能を備えるPDFビューワー、それがSkimです。Skimに比べればPreview.appなど取るに足らない存在。「PDFビューワー四天王」のうち、その最上位に君臨するアプリケーションこそがSkimです(四天王とかいいつつ、Skim、Preview、Acrobatの3人しかいないのはお約束)。


▲SkimでPDFをオープンし、「AppleScriptってなんだろう?」の文字列を選択

ただ、そんなグレートな存在のSkimでも、「選択中のテキストを取得する」という処理を書いたことはありませんでした。

Skimの「selection」によって取得されるのがテキストではなくRTFなので、AppleScriptの基本的な機能ではこのRTFはひどく扱いが難しいデータ「でした」。

しかし、Cocoaの機能を利用することで、テキストへの変換は可能です。

それでも、Cocoaが期待するRTFのデータとAppleScriptの世界のRTFのデータ同士の変換が難儀でした。食後の腹ごなしに行うには手に余るといったレベル。

そこで、お気軽データ変換の最後の砦であるクリップボードを経由してRTFをAppleScriptの世界からCocoaの世界に受け渡してみたところ、大成功。あとは、PDFから取得したテキストデータによくあることですが、日本語のテキストだとUnicodeのNormalize方法の問題によりひらがな/カタカナと濁点や半濁点が分離した状態で返ってきました。

これについても、Cocoaの機能を利用してNormalizeを行い、常識的なテキストに変換できました。

AppleScript名:Skimでオープン中のPDFの選択中のテキストを返す
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/09/16
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

tell application "Skim"
  tell front document
    set aSel to selection
    
repeat with i in aSel
      set aCon to contents of i
      
set rList to RTF of aCon
      
      
set sCon to ""
      
repeat with ii in rList
        set the clipboard to ii
        
set aText to getClipboardAsText() of me
        
set aCon to aCon & aText
      end repeat
      
      
set aStr to textfy(aCon) of me
      
return aStr
    end repeat
  end tell
end tell

–Normalize Unicode Text in NFKC
on textfy(aText as string)
  set aStr to current application’s NSString’s stringWithString:aText
  
set aNFKC to aStr’s precomposedStringWithCompatibilityMapping()
  
return aNFKC as string
end textfy

–Clipboard内の情報をテキストとして取得する
on getClipboardAsText()
  — get the pasteboard items
  
set theClip to current application’s NSPasteboard’s generalPasteboard()
  
set pbItems to theClip’s pasteboardItems()
  
  
set theStrings to {}
  
  
repeat with anItem in pbItems
    if (anItem’s types()’s containsObject:(current application’s NSPasteboardTypeString)) then
      set end of theStrings to (anItem’s stringForType:(current application’s NSPasteboardTypeString)) as text
    end if
  end repeat
  
  
return theStrings as text
end getClipboardAsText

★Click Here to Open This Script 

とか言ってたら、夕飯の買い物に出かけようとした頃にShane Stanleyから「もっとシンプルに書けるよー」というサンプルが届いて脱力しました。もっと簡潔に書けたようです(同一サンプルで日本語データに対してチェックずみ)。

ただ、PDFから文字取り出ししたあとは、Unicodeの再Normalizeは割とやらないといけないケースが多いので、選択部分(selection)からRTFじゃなくてcharacterでデータを取り出せばよかったというあたりが反省点でしょうか。

set theText to ""
tell application "Skim"
  tell front document
    set aSel to selection
    
repeat with anItem in aSel
      set theText to theText & (characters of anItem) as text
    end repeat
  end tell
end tell
return theText

★Click Here to Open This Script 

Posted in Clipboard RTF Text | Tagged 10.12savvy 10.13savvy 10.14savvy NSPasteboard NSPasteboardTypeString NSString Skim | Leave a comment

tableExtractor

Posted on 9月 15, 2019 by Takaaki Naganoya

Safariで表示中のページのうち、テキストを選択中のキーワードを含む表をCSVファイルに書き出してNumbersでオープンするAppleScriptです。

–> Download tableExtractor Run-Only (Code-Signed Executable including Framework in its bundle)

–> Watch Demo movie

実行前にSafariの「開発」メニューから、「スマート検索フィールドからのJavaScriptの実行を許可」「AppleEventからのJavaScriptの実行を許可」を実行しておく必要があります(実行済みの場合には必要ありません)。


▲Safariで表示中のページのうち、CSV書き出ししたい表のテキストを選択


▲本Scriptで表をCSVに書き出してNumbersでオープン

以前に作成した「Safariで表示中のPageの選択中の文字を含む表データを取得」Scriptがいい線を行っていた(あらかじめ表中のテキストを選択しておく、という前提条件がかったるいかと思っていたのに、そうでもなかった)ので、ありもののサブルーチンを追加して、表部分のHTMLからのタグ削除やCSV書き出しなどを行えるようにしました。

本Scriptは表データをCSV書き出しする必要はどこにもないのですが、Numbers v6.1に「表を新規作成して表のセル数を指定すると多くの場合にエラーになる」というバグがあるので、Numbersを直接操作してデータ出力させることはやっていません。

処理時間もさほどかからないので、表示中のページのすべての表オブジェクトをCSV化したり、表を選択するUIを実装して、「どの表を出力するか?」という選択処理をしてもいいかもしれません。


▲漫然とMacOS日本語で書き出ししたため文字化けしたもの(左)、UTF8を指定して書き出ししたために文字化けしなくなったもの(右)

途中でCSV書き出しした表データに文字化けが発生していたのですが、これはUTF8でファイル書き出ししていなかったためでした。

本Scriptは前バージョンよりもキーワードの検出処理をていねいに行なっています。各TableのHTMLに対してタグの除去を行なったうえでWebブラウザ上で選択中の文字列を含んでいるかどうかをチェックしています。

AppleScript名:tableExtractor.scptd
— Created 2019-09-15 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "HTMLReader" –https://github.com/nolanw/HTMLReader

property NSString : a reference to current application’s NSString
property HTMLDocument : a reference to current application’s HTMLDocument
property NSMutableArray : a reference to current application’s NSMutableArray

tell application "Safari"
  set dList to every document –Sometimes "count every document"causes error
  
if length of dList = 0 then return
  
  
–Get URL
  
tell front document
    set aURL to URL
  end tell
  
  
–Get Selected Text
  
set aRes to do JavaScript "var selObj = window.getSelection();
  var selStr = (selObj).getRangeAt(0);
  unescape(selStr);"
in front document
  
  
if aRes = "" then return
end tell

set aRes to filterATableAndPaseCells(aURL, aRes) of me
if aRes = false then
  display notification "I could not filter table data…"
  
return
end if

–Save 2D List to temp CSV file on desktop folder
set savePath to ((path to desktop) as string) & (do shell script "uuidgen") & ".csv"
saveAsCSV(aRes, savePath) of me

tell application "Numbers"
  activate
  
open file savePath
end tell

on filterATableAndPaseCells(aURL, aKeyword)
  set aData to (do shell script "curl " & aURL)
  
set aHTML to current application’s HTMLDocument’s documentWithString:(aData as string)
  
  
–Table要素をリストアップ
  
set eList to (aHTML’s nodesMatchingSelector:"table")
  
  
–Table要素のうちSafari上で選択中の文字列を含むものをサーチ(指定データを含むものを抽出)
  
set hitF to false
  
repeat with i in eList
    set cellList to i’s children()’s array()
    
set htmlSource to i’s serializedFragment() as string –HTML source
    
set html2 to trimStrFromTo(htmlSource, "<", ">") of me
    
set html3 to repChar(html2, return, "") of me
    
    
if html3 contains aKeyword then
      set hitF to true
      
exit repeat
    end if
  end repeat
  
if hitF = false then return false
  
  
–Count columns of Table Header
  
set aTableHeader to (i’s nodesMatchingSelector:"tr")’s firstObject()
  
set hList to aTableHeader’s nodesMatchingSelector:"th"
  
set hStrList to {}
  
repeat with i1 in hList
    set the end of hStrList to i1’s textContent() as string
  end repeat
  
set hLen to length of hStrList –count columns
  
  
–Acquire whole table body contents
  
set aTableBody to (i’s nodesMatchingSelector:"tbody")’s firstObject()
  
set bList to aTableBody’s nodesMatchingSelector:"td"
  
set bbList to {}
  
repeat with i2 in bList
    set the end of bbList to i2’s textContent() as string
  end repeat
  
  
set tbList to makeList1DTo2D(bbList, hLen) of me
  
  
return {hStrList} & tbList
end filterATableAndPaseCells

–1D Listを2D化
on makeList1DTo2D(orig1DList, aMax)
  set tbList to {}
  
set tmpList to {}
  
set aCount to 1
  
  
repeat with i3 in orig1DList
    set j to contents of i3
    
set the end of tmpList to j
    
    
if aCount ≥ aMax then
      set aCount to 1
      
set the end of tbList to tmpList
      
set tmpList to {}
    else
      set aCount to aCount + 1
    end if
  end repeat
  
  
return tbList
end makeList1DTo2D

on trimStrFromTo(aParamStr, fromStr, toStr)
  set theScanner to current application’s NSScanner’s scannerWithString:aParamStr
  
set anArray to current application’s NSMutableArray’s array()
  
  
repeat until (theScanner’s isAtEnd as boolean)
    set {theResult, theKey} to theScanner’s scanUpToString:fromStr intoString:(reference)
    
    
theScanner’s scanString:fromStr intoString:(missing value)
    
set {theResult, theValue} to theScanner’s scanUpToString:toStr intoString:(reference)
    
if theValue is missing value then set theValue to ""
    
    
theScanner’s scanString:toStr intoString:(missing value)
    
    
anArray’s addObject:theValue
  end repeat
  
  
if anArray’s |count|() = 0 then return aParamStr
  
  
copy aParamStr to curStr
  
repeat with i in (anArray as list)
    set curStr to repChar(curStr, fromStr & i & toStr, "") of me
  end repeat
  
  
return curStr
end trimStrFromTo

on repChar(aStr, targStr, repStr)
  set aString to current application’s NSString’s stringWithString:aStr
  
set bString to aString’s stringByReplacingOccurrencesOfString:targStr withString:repStr
  
set cString to bString as string
  
return cString
end repChar

–2D List to CSV file
on saveAsCSV(aList, aPath)
  –set crlfChar to (ASCII character 13) & (ASCII character 10)
  
set crlfChar to (string id 13) & (string id 10)
  
set LF to (string id 10)
  
set wholeText to ""
  
  
repeat with i in aList
    set newLine to {}
    
    
–Sanitize (Double Quote)
    
repeat with ii in i
      set jj to ii as text
      
set kk to repChar(jj, string id 34, (string id 34) & (string id 34)) of me –Escape Double Quote
      
set the end of newLine to kk
    end repeat
    
    
–Change Delimiter
    
set aLineText to ""
    
set curDelim to AppleScript’s text item delimiters
    
set AppleScript’s text item delimiters to "\",\""
    
set aLineList to newLine as text
    
set AppleScript’s text item delimiters to curDelim
    
    
set aLineText to repChar(aLineList, return, "") of me –delete return
    
set aLineText to repChar(aLineText, LF, "") of me –delete lf
    
    
set wholeText to wholeText & "\"" & aLineText & "\"" & crlfChar –line terminator: CR+LF
  end repeat
  
  
if (aPath as string) does not end with ".csv" then
    set bPath to aPath & ".csv" as Unicode text
  else
    set bPath to aPath as Unicode text
  end if
  
  
writeToFileUTF8(wholeText, bPath, false) of me
  
end saveAsCSV

on writeToFileUTF8(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 writeToFileUTF8

★Click Here to Open This Script 

Posted in file Internet JavaScript list Text | Tagged 10.12savvy 10.13savvy 10.14savvy HTMLDocument NSMutableArray NSString Numbers Safari | 1 Comment

htmlの並列ダウンロード処理

Posted on 9月 13, 2019 by Takaaki Naganoya

Webコンテンツ(HTML)の並列ダウンロードを行うAppleScriptです。

Webコンテンツからデータを抽出する際に、あらかじめ一括でHTMLを並列ダウンロードしておいて、ダウンロードずみのデータを一括処理すると処理時間を大幅に短縮できます。「戦場の絆」Wikiから機体データの表をすべて取得するのに、順次HTMLを取得して抽出していた場合には3〜4分程度かかっていたものを、並列ダウンロードしたのちにデータ処理するように変更すれば、これが十数秒程度にまで高速化できます。

既存のプログラムを修正してHTMLのダウンロード用に仕立ててみました。並列キュー(未処理タスク数)へのアクセスはAppleScriptからはできなかった(実行すると結果が返ってこなかった)のですが、そこに手をつけずに並列処理の完了状態を検出しています。

ダウンロードが完了したデータはlist(配列)に入るので、リクエスト数と完了リクエスト数をループ内でチェックし、完了アイテム数がリクエスト数と同じになれば終了、条件を満たさない場合でも指定のタイムアウト時間を超えたらエラー終了という処理を行なっています。

問題点は、スクリプトエディタ上では実行できるもののScript Debugger上では実行できないことです(結果が返ってきません)。AppleScriptアプレットに書き出して実行してみたところ、結果が返ってきません。ただし、Script Menuからの実行は行えます(macOS 10.12.6、10.13.6、10.14.6で同様)。XcodeのAppleScript Appのプロジェクト内で実行することはできました。

このように、ランタイム環境に実行状況が左右される点にご注意ください。ただし、そうしたマイナス面を補ってあまりあるほどダウンロードは高速です。90ファイル強のダウンロードを数秒で完了(マシン、ネットワーク速度、ダウンロード先サーバーの負荷状況、キャッシュ状態などに左右される、参考値です)するため、ダウンロード後に各HTMLからのデータ抽出も高速に行えます。

AppleScript名:htmlの並列ダウンロード処理
— Created 2019-09-13 by Takaaki Naganoya
— 2019 Piyomaru Software
—
– オリジナル: HTTP からファイルをダウンロードして、ローカルに保存する方法(shintarou_horiのブログ)
— http://shintarou-hori.hatenablog.com/entry/2014/03/15/193604

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

property |NSURL| : a reference to current application’s |NSURL|
property NSData : a reference to current application’s NSData
property NSString : a reference to current application’s NSString
property NSOperationQueue : a reference to current application’s NSOperationQueue
property NSInvocationOperation : a reference to current application’s NSInvocationOperation
property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding

property aTimer : missing value

script spd
  property mList : {}
  
property resList : {}
end script

set (mList of spd) to {}
set (resList of spd) to {}
set baseURL to "https://w.atwiki.jp/senjounokizuna/pages/"

set numList to {25, 1594, 890, 70, 1669, 82, 1717, 997, 1080, 1614, 1712, 159, 1311, 1694, 1752, 1263}

set urlList to {}
repeat with i in numList
  set the end of urlList to (baseURL & i as string) & ".html"
end repeat

set aLen to length of urlList
set paramObj to {urls:urlList, timeOutSec:60}

–set (resList of spd) to downloadHTMLConcurrently(urlList, 60) of me
my performSelectorOnMainThread:"downloadHTMLConcurrently:" withObject:(paramObj) waitUntilDone:true
return length of (mList of spd)

on downloadHTMLConcurrently:paramObj
  set urlList to (urls of paramObj) as list
  
set timeOutS to (timeOutSec of paramObj) as real
  
set aLen to length of urlList
  
  
repeat with i in urlList
    set j to contents of i
    
set aURL to (|NSURL|’s URLWithString:j)
    
set aQueue to NSOperationQueue’s new()
    
set aOperation to (NSInvocationOperation’s alloc()’s initWithTarget:me selector:"execDL:" object:aURL)
    (
aQueue’s addOperation:aOperation)
  end repeat
  
  
–Check Completion
  
set compF to false
  
set loopTimes to (timeOutS * 10)
  
repeat loopTimes times
    if length of (mList of spd) = aLen then
      set compF to true
      
exit repeat
    end if
    
delay 0.1
  end repeat
  
  
if compF = false then error "Concurrent download timed out"
end downloadHTMLConcurrently:

on execDL:theURL
  set receiveData to NSData’s alloc()’s initWithContentsOfURL:theURL
  
if receiveData = missing value then
    return
  end if
  
  
set aFileName to theURL’s |lastPathComponent|()
  
my performSelectorOnMainThread:"saveData:" withObject:{receiveData, aFileName} waitUntilDone:false
end execDL:

on saveData:theDataArray
  copy theDataArray to {theData, saveFileName}
  
set aCon to NSString’s alloc()’s initWithData:theData encoding:NSUTF8StringEncoding
  
set the end of (mList of spd) to {fileName:saveFileName as string, contentsData:aCon as string}
end saveData:

★Click Here to Open This Script 

Posted in list Network URL | Tagged 10.12savvy 10.13savvy 10.14savvy NSData NSInvocationOperation NSOperationQueue NSString NSURL NSUTF8StringEncoding | Leave a comment

sdefの内容を強引に取得する

Posted on 9月 12, 2019 by Takaaki Naganoya

指定アプリケーションのsdefの内容を強引に取得するAppleScriptです。

スクリプトエディタをAppleScriptからコントロールして、指定アプリケーションのsdef(AppleScript用語辞書)の内容を取得します。もちろん、AppleScript対応のアプリケーションに限ります。対応/非対応の判定はあらかじめ行なっておいてください。

そもそも、なんでこれが必要になったかといえば、各種AppleScript Libraryの整備のための資料として、既存のAppleScript対応アプリケーションの識別コード(4文字コード)を取得して確認しておきたかったためです。

そこで、まっとうな方法だと、

step 1:対象アプリケーションのInfo.plistの内容を確認してsdefの名称を取得

step 2:アプリケーションバンドル内のsdefを取得

という流れになります。これで済めば処理は非常に短時間に完了します。ファイル処理だけなので。

しかし、実際にやってみると…………標準的な方法でsdefを取得できないアプリケーションがいくつか存在することに気づきます。

(1)Adobe Illustratorなど

バンドル内にsdefが存在しない。動的にプログラムでsdefを生成しているのでは?

(2)scriptSuite+scriptTerminologyに分かれている場合

バンドル内にsdefではなく.scriptSuiteファイルと.scriptTerminologyファイルを格納。テキストエディット(TextEdit.app)やスクリプトエディタ(Script Editor.app)などが該当する。

また、一部のアプリケーション(MS-Officeなど)ではsdefファイルのうち一部を外部からincludeしているため、アプリケーションバンドル内のsdefファイルを読んだだけでは完全なsdefが取得できないといった問題もあります。

そこで、この「スクリプトエディタをコントロールしてsdefの内容を取得する」という頭の悪そうな処理が必要になりました。シェルのsdefコマンドを使えばいいんじゃない? という意見も出てきそうですが、現行環境(macOS 10.14.x)でsdefコマンドはうまく動いていないように見えます。

AppleScript名:sdefの内容を強引に取得する.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/09/12
—
–  Copyright © 2019 jp.piyomarusoft, All Rights Reserved
—

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

set aPath to (choose file of type "com.apple.application-bundle" default location (path to applications folder) with prompt "Select an application")
set sdefContents to getForceSdefContentsUsingSE2(aPath) of me

on getForceSdefContentsUsingSE2(anAlias)
  try
    tell application id "com.apple.ScriptEditor2"
      open anAlias
      
tell front document
        set dictPath to path
      end tell
    end tell
  on error erM
    return erM
  end try
  
  
  
tell current application
    set aSdef to read dictPath
  end tell
  
  
tell application id "com.apple.ScriptEditor2"
    tell front document
      close without saving
    end tell
  end tell
  
  
return aSdef
end getForceSdefContentsUsingSE2

★Click Here to Open This Script 

Posted in file sdef | Tagged 10.12savvy 10.13savvy 10.14savvy Script Editor | Leave a comment

指定フォルダ以下のアプリケーションを取得して、Scriptabilityをチェック

Posted on 9月 11, 2019 by Takaaki Naganoya

指定フォルダ以下のアプリケーションをSpotlightで検索して、それらのうちAppleScript対応の(Scriptableな)ものを集計するAppleScriptです。

Shane StanleyのMetadata Libを呼び出してSpotlight検索を行い、アプリケーションファイルの一覧を取得。その後、各アプリケーションのInfo.plistの情報を取得してNSAppleScriptEnabled=trueのアプリケーションのパスをlist(array)に追加します。

ただし、一部のApple製のアプリケーションに見られるように、NSAppleScriptEnabled=trueであるにもかかわらず、実際のAppleScriptサポート機能が実装されていないものもありますので(例:iBooks Author)これだけではScript対応かどうかの完全な判断は行えません。

一方、AppleScriptなどのOSA言語によるコントロールに対応していないアプリケーションはこれで完全にフィルタできます。NSAppleScriptEnabledのエントリがInfo.plistに存在しないものは非対応アプリケーションです。

非対応のアプリケーションに対して、AppleScriptからは起動、終了、ファイルのオープン、印刷などの基礎的な操作やアプリケーションの情報取得(名称やバージョンなど)、Finder経由で指定書類をアプリケーションでオープン、ぐらいの操作。また、GUI Scriptingによるメニューやボタンの強制操作しかできません。

AppleScript名:指定フォルダ以下のアプリケーションを取得して、Scriptabilityをチェック.scptd
— Created 2019-09-11 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use mdLib : script "Metadata Lib" version "2.0.0" –https://macosxautomation.com/applescript/apps/Script_Libs.html

set origPath to POSIX path of (choose folder default location (path to applications folder))
set aResList to mdLib’s searchFolders:{origPath} searchString:("kMDItemContentType == %@") searchArgs:{"com.apple.application-bundle"}

set allCount to length of aResList
set sList to {}

repeat with i in aResList
  set j to contents of i
  
set sRes to retAppScriptabilityFromBundleIPath(j) of me
  
if sRes = true then
    set the end of sList to j
  end if
end repeat

return (length of sList)
–> 297

–指定パスからアプリケーションのScriptabilityをbooleanで返す
on retAppScriptabilityFromBundleIPath(appPath as string)
  set aDict to (current application’s NSBundle’s bundleWithPath:appPath)’s infoDictionary()
  
set aRes to aDict’s valueForKey:"NSAppleScriptEnabled"
  
if aRes = missing value then return false
  
return aRes as boolean
end retAppScriptabilityFromBundleIPath

★Click Here to Open This Script 

Posted in file list Spotlight | Tagged 10.12savvy 10.13savvy 10.14savvy NSBundle | Leave a comment

choose location script Library

Posted on 9月 8, 2019 by Takaaki Naganoya

位置情報リストを与え、リスト+地図表示していずれかを選択するUser Interfaceを提供するAppleScriptライブラリです。

–> Download choose location.scptd (To ~/Library/Script Libraries/)

リストに入れた所定のラベルを持つレコードを与えると、地図表示して選択できます。

set aPlaceList to {{title:"Ginza", latitude:"35.67229109", longitude:"139.76575278"}....}

のような名称、緯度、経度のセットを与えます。各位置情報については適宜計算してください(自分はYahoo!の住所ジオコーダーサービスを利用しています)。

地図の表示タイプをGUI上から切り替えられますが、AppleScriptのオプション「initial map type」で初期表示地図タイプを指定できます。


▲初期表示タイプ「map」「satellite」「mixture」(左より)

sdefがいまひとつうまく想定どおりに動いていません。位置情報リストのラベルを予約語として動作させたかったのに、そう動いていませんが、とりあえず現状はこんな感じです(^ー^;; あと、Optional=”Yes”を指定しても省略可能表示になっていないのが謎です。いいのか悪いのか、機能自体に影響がないので現状このままですが、、、

AppleScript名:choose loc sample script
— Created 2019-09-08 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use cLoc : script "choose location"

set aPlaceList to {{title:"Ginza", latitude:"35.67229109", longitude:"139.76575278"}, {title:"Shinjuku", latitude:"35.69096528", longitude:"139.70403520"}, {title:"Kyoto", latitude:"35.00394764", longitude:"135.76277689"}, {title:"Shibuya", latitude:"35.66621547", longitude:"139.71090224"}, {title:"Marunouchi", latitude:"35.67982632", longitude:"139.76364660"}, {title:"Omote-sando", latitude:"35.66621547", longitude:"139.71090224"}, {title:"Nagoya-Sakae", latitude:"35.16556738", longitude:"136.90693150"}, {title:"Fukuoka-Tenjin", latitude:"33.58682428", longitude:"130.39764326"}, {title:"Shinsai-bashi", latitude:"34.67225640", longitude:"135.49985757"}}

set cRes to (choose location from aPlaceList main message "Select Apple Retail Store in Japan" sub message "These stores are almost same. All products are same. The most of visitors are waiting people to repair their broken products." with size {900, 500} initial map type map)

★Click Here to Open This Script 

Posted in dialog geolocation GUI Script Libraries sdef | Tagged 10.12savvy 10.13savvy 10.14savvy | 1 Comment

display table Script Library

Posted on 9月 7, 2019 by Takaaki Naganoya

2D List(二次元配列)データを気軽に表UIでプレビューするUser Interfaceを提供するdisplay table Script Library+サンプルコードです。

–> Download displayTable.scptd (To ~/Library/Script Libraries/)

表UIを提供する部品としては、Shane StanleyのMyriad Tables Libが存在しており、ひじょうに充実した機能を備えているため、同様でかつ機能が低いものを提供する必要はないはずです。

ですが、同ライブラリはバンドル内にFrameworkを含んでおり、SIPによる機能制限でそのままではmacOS 10.14以降の環境ではこのライブラリを(スクリプトエディタでは)呼べないなどの問題があります。ホームディレクトリ以下のFrameworkのバイナリを呼べないわけです。Script Debuggerを使ったり、アプレットとして書き出せばクリアできるものの、利用シーンが限定されるきらいがありました(このあたり、GUIなしのsdefつきアプリケーションとして仕立ててライブラリのバンドル内に入れれば回避できるのではないかと思っていますが、どうなりますやら)。

そこで、2D List(二次元配列)データのプレビューなど、最低限の機能をそなえたライブラリを(主に自分用に)作ってみたものです。もともと、NSTableViewで表示するためには2D List(2次元配列)ではなくRecord in List(行ごとに各フィールドが属性ラベルの付いたRecord)になっている必要があります。この、2D List → Record in Listの変換処理が面倒なので、その部分を中心に、汎用部品として使えるように機能をまとめてみました。

NSTableViewの各セルのタイトルをRecord in Listの各ラベル値に設定しており、上記のデータは、

(NSArray) {
	{
		ダッシュ時間:"2.2cnt",
		ダッシュ距離:"?m",
		タックルダメージ:"20",
		ダッシュ速度:"208km/h",
		ジャンプ速度:"167km/h",
		硬直時間:"38f",
		セッティング名:"旋(旋回)    ",
		アーマー値:"284",
		歩行速度:"100km/h",
		旋回速度:"10.9rpm",
		備考:""
	},

...........

	{
		ダッシュ時間:"2.1cnt",
		ダッシュ距離:"?m",
		タックルダメージ:"20",
		ダッシュ速度:"180km/h",
		ジャンプ速度:"144km/h",
		硬直時間:"38f",
		セッティング名:"装(装甲)    ",
		アーマー値:"343",
		歩行速度:"100km/h",
		旋回速度:" 9.7rpm",
		備考:""
	}
}

という、日本語の属性ラベルのついたRecord(Dictionary)に変換・表示しています。

dialog上のアイコン表示部品を画像のプレビュー用に使ってみたりと、例によって好き放題やっていますが、アイコン関連のファイルパス/URLを指定しなければ通常の動作を行います。

AppleScript名:display table by list sample
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/25
—
–  Copyright © 2019 jp.piyomarusoft, All Rights Reserved
—
use AppleScript version "2.5" — El Capitan (10.11) or later
use framework "Foundation"
use scripting additions

use easyTable : script "display table by list"

set msURL to "http://web.gundam-kizuna.jp/sp/image/index/img/p/QBP89Z-T_2o62sJWBQC7BSsw08wZuZ28keecHZs9Io4"

set aList to {{"旋(旋回) ", "284", "208km/h", "2.2cnt", "?m", "167km/h", "10.9rpm", "38f", "20", "100km/h", ""}, {"硬(硬直減) ", "286", "206km/h", "2.1cnt", "?m", "165km/h", "10.3rpm", "34f", "20", "100km/h", ""}, {"歩(歩行) ", "293", "206km/h", "2.2cnt", "?m", "165km/h", "10.3rpm", "38f", "20", "111km/h", ""}, {"跳(ジャンプ)", "263", "202km/h", "2.1cnt", "?m", "183km/h", "10.3rpm", "39f", "20", "100km/h", ""}, {"走(ダッシュ)", "248", "224km/h", "2.3cnt", "?m", "161km/h", "10.3rpm", "40f", "20", "100km/h", ""}, {"機(機動) ", "243", "216km/h", "2.2cnt", "?m", "177km/h", "10.6rpm", "39f", "20", "100km/h", ""}, {"推(ブースト)", "296", "196km/h", "2.4cnt", "?m", "157km/h", "10.0rpm", "38f", "20", "100km/h", ""}, {"突(タックル)", "298", "190km/h", "2.1cnt", "?m", "152km/h", " 9.7rpm", "38f", "30", "100km/h", ""}, {"装(装甲) ", "343", "180km/h", "2.1cnt", "?m", "144km/h", " 9.7rpm", "38f", "20", "100km/h", ""}}

set fLabels to {"セッティング名", "アーマー値", "ダッシュ速度", "ダッシュ時間", "ダッシュ距離", "ジャンプ速度", "旋回速度", "硬直時間", "タックルダメージ", "歩行速度", "備考"}

set aRes to (display table by list aList main message "項目の選択" sub message "適切なものを以下からえらんでください" size {1200, 400} labels fLabels icon msURL timed out 5)

★Click Here to Open This Script 

Posted in GUI Script Libraries sdef URL | Tagged 10.12savvy 10.13savvy 10.14savvy | Leave a comment

2つのレコードのキーの重複を計算

Posted on 9月 7, 2019 by Takaaki Naganoya

2つのレコードのキーの重複を検出するAppleScriptです。

こういう処理がお手軽にできるようになったので、macOS 10.10以降のAppleScriptでないとプログラムが組めなくなっている今日このごろ。死ぬほど努力してOld Style AppleScript(Cocoaの機能を使わない)だけで組めないこともないですが、それだけで半日は費やして数百行のプログラムになってしまいそうです。

というわけで、Cocoaの機能を利用した「ありもの」のルーチンを組み合わせるだけでほぼ完成。2つのレコードのキーの重複計算を行います。

どういう用途で使うかといえば、パラメータつきのURLに対して追加パラメータを付加したい場合です。URLからレコード形式でパラメータを分離し、追加パラメータ(レコード形式)を足し算する「前」に、2つのレコード間で重複キーがないかチェックする、という用途です。

では、2つのレコードの加算はどーするのか? という話になりますが、それは単に&演算子で加算するだけです。

set aRec to {abc:"1", bcd:"2"}
set bRec to {ccc:"0", ddd:"9"}
set cRec to aRec & bRec
–> {abc:"1", bcd:"2", ccc:"0", ddd:"9"}

★Click Here to Open This Script 

AppleScript名:2つのレコードのキーの重複を計算.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/09/06
—
–  Copyright © 2019 jp.piyomarusoft, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property NSSet : a reference to current application’s NSSet
property NSCountedSet : a reference to current application’s NSCountedSet
property NSMutableDictionary : a reference to current application’s NSMutableDictionary

set aRec to {autoplay:"1", hd:"9"}
set bRec to {v:"GP_tVXTYdmY", t:"120", hd:"3"}

set dupKeys to detectDuplicateKeysInTwoRecords(aRec, bRec) of me
–> {"hd"}

on detectDuplicateKeysInTwoRecords(aRec, bRec)
  set aDict to NSMutableDictionary’s dictionaryWithDictionary:aRec
  
set bDict to NSMutableDictionary’s dictionaryWithDictionary:bRec
  
  
set aKeyList to (aDict’s allKeys()) as list
  
set bKeyList to (bDict’s allKeys()) as list
  
  
set allKeyList to aKeyList & bKeyList
  
  
set aRes to returnDuplicatesOnly(allKeyList) of me
  
return aRes
end detectDuplicateKeysInTwoRecords

–1D Listから重複項目のみ返す
on returnDuplicatesOnly(aList as list)
  set aSet to NSCountedSet’s alloc()’s initWithArray:aList
  
set bList to (aSet’s allObjects()) as list
  
  
set dupList to {}
  
repeat with i in bList
    set aRes to (aSet’s countForObject:i)
    
if aRes > 1 then
      set the end of dupList to (contents of i)
    end if
  end repeat
  
  
return dupList
end returnDuplicatesOnly

★Click Here to Open This Script 

Posted in list Record | Tagged 10.12savvy 10.13savvy 10.14savvy NSCountedSet NSMutableDictionary NSSet | Leave a comment

指定URLのMS名を取得する v2b

Posted on 9月 4, 2019 by Takaaki Naganoya

edama2さんから投稿していただいた、指定URLの初出の指定タグ要素を抽出するAppleScriptです。

戦場の絆Wiki上の指定ページ上の指定タグでマークされたテキストを取得します。

ブログを見ていて思いつき、前に作りかけていたのを清書して送ります。

名前は「指定URLのMS名を取得するv2b」です。
内容はWKWebviewでページを読み込んで、javascriptで要素を取得しています。
前の二つよりスマートではありませんが、こんなやり方もあるってことで...

色々書き換えているうちに元がないですが、元ネタはapplescriptの穴からです。

プログラムも短いわけではなく、処理速度も速いわけでもなく(自分の環境で9秒ぐらい)、ただ見ただけだと「????」という内容ですが、本プログラムの価値は処理対象ではなく、

AppleScriptからWkWebViewに対して任意のJavaScriptを実行して処理しているサンプルである

という1点に尽きます。これはー、セキュリティ上のしばりがきつくて、けっこう大変なんですよ(遠い目)。

以前、WKWebView上にYouTubeの指定URLのムービーを表示するというScriptを掲載したことがありますが、本当はこの上でJavaScriptを実行して指定の再生ポジションに再生位置をジャンプさせるといった処理を行いたかったのですが、WKWebView相手に(任意の)JavaScriptを実行させられず、時間切れで諦めたことがありました(そして絶賛放置中)。なるほど、こう書くんですねー。

あとは、

tell AppleScript

ってなんなんでしょう(^ー^;; 初めて見かける記述のオンパレードがけっこうショッキングです。

自分は「癖のないプログラムを読みやすく書く派」を自称していますが、日本国内にも割と海外のScripterに紹介したい(変わった)人たちがいて、edama2さんとMacLab.さんはその中に必ず入ってくる人たちでしょう。

AppleScript名:指定URLのMS名を取得する v2b.scpt
—
–  Created by: edama2
–  Created on: 2019/09/04
—
use AppleScript
use scripting additions
use framework "Foundation"
use framework "WebKit"

property _js_result : ""

on run
  my main()
end run

on main()
  set my _js_result to ""
  
  
set aURL to "https://w.atwiki.jp/senjounokizuna/pages/1650.html"
  
set myJs to "var result = document.getElementsByTagName(’h3’)[0].innerHTML;
  webkit.messageHandlers.oreore.postMessage(result);"
–>返信用に必要
  
set paramObj to {targetURL:aURL, javascript:myJs}
  
  
my performSelectorOnMainThread:"makeWebContents:" withObject:(paramObj) waitUntilDone:true
  
  
return my _js_result as text
end main

on makeWebContents:paramObj
  
  
set {targetURL:aURL, javascript:myJs} to paramObj
  
  
# 下準備
  
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 new()
  
  
#javascriptからname を取り出す
  
set myJs to myJs as text
  
tell AppleScript
    set tmp to text item delimiters
    
set text item delimiters to "webkit.messageHandlers."
    
set stringList to myJs’s text items
    
set aText2 to stringList’s item 2
    
set text item delimiters to ".postMessage("
    
set stringList2 to aText2’s text items
    
set scriptName to stringList2’s item 1
    
set text item delimiters to tmp
  end tell
  
  
#ページ読み込み後に実行するjavascriptの仕込み
  
set userScript to current application’s WKUserScript’s alloc()’s initWithSource:myJs injectionTime:(current application’s WKUserScriptInjectionTimeAtDocumentEnd) forMainFrameOnly:true
  
tell current application’s WKUserContentController’s new()
    addUserScript_(userScript)
    
addScriptMessageHandler_name_(me, scriptName)
    
aConf’s setUserContentController:it
  end tell
  
  
#WebViewを作成&読み込み
  
tell (current application’s WKWebView’s alloc()’s initWithFrame:(current application’s CGRectZero) configuration:aConf)
    setNavigationDelegate_(me)
    
loadRequest_(theRequest)
    
    
set hitF to false
    
repeat (minutes * 1000) times
      set isLoading to isLoading() as boolean
      
if not isLoading then
        set hitF to true
        
exit repeat
      end if
      
delay "0.001" as real
    end repeat
    
  end tell
  
  
return hitF
end makeWebContents:

#javascriptの結果を受信
on userContentController:myUserContentController didReceiveScriptMessage:aMessage
  set my _js_result to aMessage’s body() as text
  
return my _js_result
end userContentController:didReceiveScriptMessage:

★Click Here to Open This Script 

Posted in JavaScript URL | Tagged 10.12savvy 10.13savvy 10.14savvy NSURL NSURLRequest WKUserContentController WKUserScript WKWebView WKWebViewConfiguration | Leave a comment

Safariで表示中のPageの選択中の文字を含む表データを取得

Posted on 9月 3, 2019 by Takaaki Naganoya

Safari上で一部のテキストを選択した「表」のデータをHTMLReaderフレームワークを利用してparseし、2D Listとして取得するAppleScriptです。

Web上の表データをそのまま利用したいケースが多々あります。こんな小さなデータではなく、数百個にわたる表データをインポートして使いたいというケースです。

そのときに作った部品を転用して、より一般的な用途に使えるようにしたのが本Scriptです。ただし、さまざまな用途に使って鍛えたというものでもなく、AppleのWebドキュメントやWikiの内容の抽出など、割と「規則性の高そうなコンテンツ」で利用してみました。

本来は、複数ページの特定の表を指定してデータを取得する用途に用いているものなので、本Scriptのように「選択中の文字列を含む表」といった、のどかな使い方はしません。動作内容がわかりやすいように作り変えたためにこのような仕様になっています。

どこぞのオンラインストアの諸元をまとめた表をWeb上からくすねてくる、とかいう用途だと、割と表が込み入って(JavaScriptを仕込んでソートし直せるようにしてあるとか)いるケースがあるので、どのページのどの表にでもあまねく利用できるという種類のものではありません。

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

HTMLReader.frameworkを利用するためには、macOS 10.14以降だとSIPを解除するかScript Debugger上で動かすか、AppleScriptアプレット内に組み込んで実行することになります。

AppleScript名:Safariで表示中のPageの選択中の文字を含む表データを取得.scptd
— Created 2019-09-02 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "HTMLReader" –https://github.com/nolanw/HTMLReader

property NSString : a reference to current application’s NSString
property HTMLDocument : a reference to current application’s HTMLDocument
property NSMutableArray : a reference to current application’s NSMutableArray

tell application "Safari"
  set dList to every document –Sometimes "count every document"causes error
  
if length of dList = 0 then return
  
  
–Get URL
  
tell front document
    set aURL to URL
  end tell
  
  
–Get Selected Text
  
set aRes to do JavaScript "var selObj = window.getSelection();
  var selStr = (selObj).getRangeAt(0);
  unescape(selStr);"
in front document
  
  
if aRes = "" then return
end tell

set aRes to filterATableAndPaseCells(aURL, aRes) of me
–> {{"Objective-C and AppleScript class", "Attributes (script term, if different)", "Relationships"}, {"NSObjectImplements the item AppleScript class. For any scriptable Objective-C class that inherits from NSObject, the AppleScript class it implements inherits from the item class (and inherits the class property and the properties property).", "class name (class), properties", ""}, {"NSApplicationImplements the application AppleScript class.", "name, active flag (frontMost), version", "documents, windows (both accessible as ordered relationship)"}, {"NSDocumentImplements the document AppleScript class.", "location of the document’s on-disk representation (path); last component of filename (name); edited flag (modified)", ""}, {"NSWindowImplements the window AppleScript class.", "title (name); various binary-state attributes: closeable, floating, miniaturized, modal, resizable, titled, visible, zoomable", "document"}}

on filterATableAndPaseCells(aURL, aKeyword)
  set aData to (do shell script "curl " & aURL)
  
set aHTML to current application’s HTMLDocument’s documentWithString:(aData as string)
  
  
–Table要素をリストアップ
  
set eList to (aHTML’s nodesMatchingSelector:"table")
  
  
–Table要素のうちSafari上で選択中の文字列を含むものをサーチ(指定データを含むものを抽出)
  
set hitF to false
  
repeat with i in eList
    set cellList to i’s children()’s array()
    
set htmlSource to i’s serializedFragment() as string –HTML source
    
    
if htmlSource contains aKeyword then
      set hitF to true
      
exit repeat
    end if
  end repeat
  
if hitF = false then return false
  
  
–Count columns of Table Header
  
set aTableHeader to (i’s nodesMatchingSelector:"tr")’s firstObject()
  
set hList to aTableHeader’s nodesMatchingSelector:"th"
  
set hStrList to {}
  
repeat with i1 in hList
    set the end of hStrList to i1’s textContent() as string
  end repeat
  
set hLen to length of hStrList –count columns
  
  
–Acquire whole table body contents
  
set aTableBody to (i’s nodesMatchingSelector:"tbody")’s firstObject()
  
set bList to aTableBody’s nodesMatchingSelector:"td"
  
set bbList to {}
  
repeat with i2 in bList
    set the end of bbList to i2’s textContent() as string
  end repeat
  
  
set tbList to makeList1DTo2D(bbList, hLen) of me
  
  
return {hStrList} & tbList
end filterATableAndPaseCells

–1D Listを2D化
on makeList1DTo2D(orig1DList, aMax)
  set tbList to {}
  
set tmpList to {}
  
set aCount to 1
  
  
repeat with i3 in orig1DList
    set j to contents of i3
    
set the end of tmpList to j
    
    
if aCount ≥ aMax then
      set aCount to 1
      
set the end of tbList to tmpList
      
set tmpList to {}
    else
      set aCount to aCount + 1
    end if
  end repeat
  
  
return tbList
end makeList1DTo2D

★Click Here to Open This Script 

Posted in JavaScript Text URL | Tagged 10.12savvy 10.13savvy 10.14savvy HTMLDocument NSMutableArray NSString Safari | 1 Comment

指定URLのMS名を取得する v2a

Posted on 9月 3, 2019 by Takaaki Naganoya

Shane Stanleyが「HTMLをXMLと見立ててアクセスすれば外部フレームワークなしに処理できて簡単だよ」と、送ってくれたサンプルScriptです。

2つの意味で焦りました。

(1)指定URLの内容をダウンロードするのに、「initWithContentsOfURL:」で処理
(2)この調子で処理したら、お手軽にREST APIも呼べそうな雰囲気

いろいろ考えさせられる内容でもあります。こういう「それ自体で何か製品を構成できるほどのサイズの処理じゃないけど、何かに絶対に使ってますよね」的な処理をBlogで公開しておくことのメリットを感じつつ、XML処理とか正規表現の処理が個人的に不得意なので、とても参考になります。

自分の用途が残念な(そんなに生産的でもなく趣味的な、という意味で)ものだったので、恐縮するばかりですー(オンラインゲームの機体のデータをWikiからまるごと引っこ抜くというものだったので)。

AppleScript名:get a title.scptd
—
–  Created by: Shane Stanley
–  Created on: 2019/09/03
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

— classes, constants, and enums used
property NSXMLDocumentTidyHTML : a reference to 512
property NSXMLDocument : a reference to current application’s NSXMLDocument
property NSString : a reference to current application’s NSString
property |NSURL| : a reference to current application’s |NSURL|
property HTMLDocument : a reference to current application’s HTMLDocument
property NSMutableArray : a reference to current application’s NSMutableArray

set aURL to "https://w.atwiki.jp/senjounokizuna/pages/1650.html"
set aRes to getTitleFromAURL(aURL) of me
–> "ジム・スナイパー  RGM-79(G)"

on getTitleFromAURL(aURL)
  set theNSURL to |NSURL|’s URLWithString:aURL
  
set {theXML, theError} to NSXMLDocument’s alloc()’s initWithContentsOfURL:theNSURL options:NSXMLDocumentTidyHTML |error|:(reference)
  
if theXML is missing value then error theError’s localizedDescription() as text
  
repeat with i from 2 to 7 by 1
    set theNodes to (theXML’s nodesForXPath:("//h" & i) |error|:(missing value))
    
if theNodes’s |count|() is not 0 then return (theNodes’s firstObject()’s stringValue()) as text
  end repeat
  
error "Header is missing"
end getTitleFromAURL

★Click Here to Open This Script 

Posted in Text URL XML | Tagged 10.12savvy 10.13savvy 10.14savvy HTMLDocument NSMutableArray NSString NSURL NSXMLDocument NSXMLDocumentTidyHTML | Leave a comment

指定URLのMS名を取得する v2

Posted on 9月 3, 2019 by Takaaki Naganoya

指定URLの初出の指定タグ要素を抽出するAppleScriptです。

たまたま、戦場の絆Wikiから各種データを自動で抽出するAppleScriptを書いたときについでに作った、各ページのh2タグで囲まれた機種名を取り出す処理部分です。


▲このデータだけ機種名がh3タグでマークされていて、例外を吸収するために汎用性を高めたのが本ルーチン

Webサイトからのデータ取り出しは割と重要な技術です。それを容易に可能にするHTMLReaderのようなFrameworkは、とても重要なパーツといえます。HTMLReaderがなければ、こんな簡単に処理することはできなかったでしょう(この些細な処理を、ではなくやりたい処理全体に対しての評価)。

# WebスクレイピングはScripter必須の技術なので、Safari/ChromeでDOMアクセス派や正規表現でソースから抽出派、XMLとして解釈してXPathでアクセスする派などいろいろありそうですが、自分はHTMLReaderを使って楽をしてデータを取り出す派 といえます

特定のURL上のHTMLの特定のタグ要素のデータを抜き出すという処理であり、かならずしもどのサイトでも万能に処理できるというわけでもありません。ただ、Wikiのような管理プログラムでコンテンツを生成しているサイトから各種データを抜き出すのは、生成されるHTMLの規則性が高くて例外が少ないため、割と簡単です。

HTMLReaderをAppleScriptから呼び出し、表データを2D Listとして解釈するなど、データ取り出しが簡単にできるようになったことは意義深いと思われます。

macOS 10.13まではスクリプトエディタ/Script Debugger上でScriptを直接実行できます。macOS 10.14以降ではSIPを解除するか、Script Debugger上で実行するか、本記事に添付したようなアプレット(バンドル内にFramework同梱)を実行する必要があります。

HTMLReaderについては、Frameworkにするよりもアプリケーション化してsdefをつけて、AppleEvent経由で呼び出す専用のバックグラウンドアプリケーションにすることも考えるべきかもしれません。ただ、すべての機能についてsdefをかぶせるためには、「こういうパターンで処理すると便利」という例をみつけてまとめる必要があります。つまり、sdefをかぶせると返り値はAppleScript的なデータに限定されるため、何らかの処理が完結した状態にする必要があります。

–> Download tagElementPicker.zip (Code Signed executable Applet)

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

Webコンテンツのダウンロードは、本ルーチンではcurlコマンドで実装していますが、いろいろ試してみたところ現時点で暫定的にこれがベストという判断を行っています。

もともと、macOS 10.7でURL Access Scriptingが廃止になったため、Webアクセスのための代替手段を確保することはScritperの間では優先順位の高い調査項目でした。

curlコマンドはその代替手段の中でも最有力ではあったものの、macOS 10.10以降のAppleScript処理系自体のScripting Bridge対応にともない、NSURLConnectionを用いたアクセスも試してきました。同期処理できて、Blocks構文の記述が必須ではないため、実装のための難易度がCocoa系のサービスでは一番低かったからです。

ただし、NSURLConnection自体がDeprecated扱いになり、後継のNSURLSessionを用いた処理を模索。いろいろ書いているうちに、処理内容がapplescript-stdlibのWebモジュールと酷似した内容になってきた(もともと同ライブラリではNSURLSessionを用いていたため)ので、この機能のためだけにapplescript-stdlibを組み込んで使ってみたりもしました。

しかし、applescript-stdlibのWebモジュールは連続して呼び出すと処理が止まるという代物であり、実際のプログラムに組み込んで使うのは「不可能」でした。1つのURLを処理するには問題はないものの、数百個のURLを処理させると止まることを確認しています。おまけに処理本体にも自分自身のsdefを用いた記述を行っているためメンテナンス性が最悪で、中身をいじくることは(自分には)無理です。

# applescript-stdlibのWebモジュールではUserAgent名がサイト側の想定しているものに該当せずアクセスを拒否されたのか、Webモジュール側の内部処理がまずいのかまでは原因追求できていません。連続処理を行うと止まるという症状を確認しているだけです

NSURLSessionによる処理については、applescript-stdlibのWebモジュールを参考にしつつもう少し書き慣れる必要がある一方で、いろいろモジュール単位で差し替えて試行錯誤したところ、curlコマンドは遅くなったり処理が止まったりすることもなく利用できています。

それでも、curlコマンド以外の選択肢を用意しておくことは重要であるため、NSURLSessionも引き続き追いかけておきたいところです。

AppleScript名:指定URLのMS名を取得する v2.scptd
— Created 2019-09-02 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "HTMLReader" –https://github.com/nolanw/HTMLReader

property NSString : a reference to current application’s NSString
property HTMLDocument : a reference to current application’s HTMLDocument
property NSMutableArray : a reference to current application’s NSMutableArray

set aURL to "https://w.atwiki.jp/senjounokizuna/pages/1650.html"
set aRes to getTitleFromAURL(aURL) of me
–> "ジム・スナイパー  RGM-79(G)"

on getTitleFromAURL(aURL)
  set aData to (do shell script "curl " & aURL)
  
set aHTML to current application’s HTMLDocument’s documentWithString:(aData as string)
  
  
–Levelの高いHeader Tagから順次低い方にサーチして返す
  
repeat with i from 2 to 7 by 1
    set aHeaderTag to "h" & i as string
    
set eList to (aHTML’s nodesMatchingSelector:aHeaderTag)
    
    
if (eList as list) is not equal to {} then
      return (eList’s firstObject()’s textContent()) as string
    end if
  end repeat
  
  
error "Header is missing"
end getTitleFromAURL

★Click Here to Open This Script 

Posted in Text URL | Tagged 10.12savvy 10.13savvy 10.14savvy HTMLDocument NSMutableArray NSString | Leave a comment

Numbersにも画期的なバグ〜特定のセルサイズの表を作るとエラーに

Posted on 8月 31, 2019 by Takaaki Naganoya

Numbers v6.1に、Keynote v9.1と同様の表作成バグが存在していることを確認しました。

Numbers v6.2でも修正されていないことを確認しました。

特定行数の表の新規作成を作成するとエラーになるという、「わざとやってないと出ないエラー」です。

それとも、何か型変換のミスとかそういう程度のひくーーいバグを作ったんじゃないかと。

とりあえず、サイズを指定せずにtableを作成して、あとから行数とカラム数を変更してもエラーになるので、回避方法がほぼありません(ーー;

データをCSV書き出ししておいてCSVをNumbersでオープンして新規に作成されたドキュメント上の表をコピーしてくる、ぐらいの回避策は考えないでもありませんが、、、、、何のためにコードを書いているのかよくわからなくなります(ーー;

探してみると、r/oではない属性値のオブジェクトに数値を突っ込んでもGUI側に反映されないなど、パラメータがいまひとつ正しく解釈されていない雰囲気が濃厚です。たとえば、active sheet上にimageを配置して、AppleScript側からpositionを変更することでY座標については制御できるものの、X座標の変更が行えていません、、、、

→ imageのpositionでX座標が制御できないバグについては、Numbers v6.2で修正されたことを確認しました

tell application "Numbers"
  tell front document
    tell active sheet
      tell image 1
        set position to {0, 0}
      end tell
    end tell
  end tell
end tell

★Click Here to Open This Script 

AppleScript名:Numbers書類上に表を新規作成.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/31
—
–  Copyright © 2019 jp.piyomarusoft, All Rights Reserved
—

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

set aWidth to 3
set aHeight to 10

tell application "Numbers"
  set aDoc to make new document
  
tell aDoc
    tell active sheet
      set tRes to make new table with properties {row count:aHeight, column count:aWidth}
    end tell
  end tell
end tell

★Click Here to Open This Script 

Posted in Bug | Tagged 10.13savvy 10.14savvy Numbers | 3 Comments

pickup color Script Library

Posted on 8月 31, 2019 by Takaaki Naganoya

指定した複数の色からどれかを選ぶコマンドを提供するAppleScriptライブラリ+呼び出しサンプルScriptです。

–> Download pickup color.scptd(To ~/Library/Script Libraries)

使い道があるんだかないんだか微妙ですが、本来であれば何らかの画像を入力して、画像内の色をポスタライズして色数を減らし、その上で本ライブラリのようなインタフェースを用いて色選択。元画像のうち選択色の占めるエリアをダイアログ上で点滅表示……という処理が行いたいところです。

アラートダイアログのアイコン表示部分は、本来なら実行をリクエストしたアプリケーションのアイコンが表示されますが、選択色のプレビュー領域に使ってみました。このアイコン表示は最前面のアプリケーションのアイコンが入るべきという「ルール」があるわけですが、最前面のアプリケーションが何であるかは分かりきっています。

別の運用方法でもっと便利になるのであれば、そういうことを試してみてもいいでしょう。


▲本来は、指定画像中の色を検出して、選択した色が表示されているエリアのみ点滅表示させたい。Xcode上で作ればできそう、、、、

また、Frameworkを呼び出してNSImageから色名をダイナミックに生成するという処理も、ライブラリとして運用するために取り外していますが、これも取り外したくはない部品です。

本来やりたい処理のすべてができているわけではないので、本ライブラリはまだまだ試作品レベルです。

色データを8ビットの整数値で与えるか、16ビットの整数値で与えるかをEnum「max255」「max65535」で表現していますが、もう少しスマートに表現したいところです。

AppleScript名:pickup color sample
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/31
—
–  Copyright © 2019 jp.piyomarusoft, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use colPic : script "pickup color"

set ap1List to {{65535, 0, 65535}, {0, 32896, 16448}, {65535, 65531, 2689}, {0, 32896, 65535}, {8608, 65514, 1548}, {46003, 46003, 46003}, {19702, 31223, 40505}}

set cRes to pickup color ap1List main message "Color Dialog" sub message "Choose a color from popup button" color max max65535

★Click Here to Open This Script 

Posted in Color GUI OSA Script Libraries sdef | Tagged 10.12savvy 10.13savvy 10.14savvy | Leave a comment

Numbersで選択範囲のセルから数字以外の文字を除去する

Posted on 8月 29, 2019 by Takaaki Naganoya

Numbersで選択範囲のセルから数字以外の文字を除去するAppleScriptです。

よく、Webブラウザ上で表示中の表データからNumbersなどの表計算ソフトにデータをコピー&ペーストして再利用することがあります。この際に、Webブラウザ上で選択中のDOM構造などを取得できると便利なのですが、いろいろ調べてみてもなかなか方法が見つかりません(自分が設計していたら、絶対に実装してるんですけれども)。

そこで、表データをWebブラウザから表計算ソフト上にコピー後にデータ加工することを考えることになります。

ExcelやNumbers上に表データをペーストして、その後で加工することをよく行います。手動で行うとかったるいので、選択範囲のセルを順次加工するScriptを日常的に作ってはストックしてあります(セル内の改行文字を削除するとか、いろいろ)。

本ScriptはmacOS 10.14.6+Numbers v6.1で検証してあります。

OS標準装備のScript Menuに入れて呼び出して利用しています。

もともと、Numbersのセル書き換え速度はそれほど速くないので、数百セルとか数千セルを一気に書き換えるような用途は考慮していません。そういう用途には、書き換えたデータをCSV書き出しして、CSVのファイルをNumbersでオープンするといった処理になると思います。

AppleScript名:選択範囲のセルから数字以外の文字を除去する
— Created 2019-08-29 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

tell application "Numbers"
  tell front document
    tell active sheet
      try
        set theTable to first table whose class of selection range is range
      on error
        return false
      end try
      
      
tell theTable
        set cellList to cell of selection range
        
set mySelectedRanges to value of cell of selection range
        
set res2 to returnNumbersCharOnlyList(mySelectedRanges) of me
        
        
repeat with i from 1 to (length of cellList)
          ignoring application responses –Async Mode
            tell item i of cellList
              set value to item i of res2
            end tell
          end ignoring
        end repeat
        
      end tell
      
    end tell
  end tell
end tell

on returnNumbersCharOnlyList(aList)
  set nList to {}
  
repeat with i in aList
    set the end of nList to returnNumberCharsOnly(i) of me
  end repeat
  
return nList
end returnNumbersCharOnlyList

on returnNumberCharsOnly(aStr)
  set anNSString to current application’s NSString’s stringWithString:aStr
  
set anNSString to anNSString’s stringByReplacingOccurrencesOfString:"[^0-9]" withString:"" options:(current application’s NSRegularExpressionSearch) range:{0, anNSString’s |length|()}
  
return anNSString as text
end returnNumberCharsOnly

★Click Here to Open This Script 

Posted in list regexp Text | Tagged 10.12savvy 10.13savvy 10.14savvy NSRegularExpressionSearch NSString | Leave a comment

天皇誕生日の計算

Posted on 8月 29, 2019 by Takaaki Naganoya

天皇誕生日を計算するAppleScriptです。

# 日本ローカルなカレンダー計算の話なので、他の国では関係のない話題です。

AppleScriptによるデータ処理テーマにおいて、各種スケジュールや日数計算(締め切りまでの営業日計算)は割とポピュラーなものです。つまり、誰でもやりたいと思うし、実際に全世界的にやった人が多いことでしょう。このレベルのものを「カレンダー計算」と呼びます。

一方、手帳やカレンダー(印刷物)の制作を行う仕事(案件)が世の中に存在しており、それを行うことを「カレンダー制作」と呼んでいます。日数計算だけでなく、その日がどのような日であるかを明確にデータ処理する必要があります。

そのうえ、デザイン優先で山のように体裁を整える必要があるのと明文化されていない作成ルールを過去の制作物から読み取れ(とくに、RFC関連規約)というご無体な指示が後出しジャンケン的に出てくる、とても関わりたくない案件の数々です。

さて、天皇誕生日は現在在位中の天皇(current emperor)の誕生日を祝日(=休日)とするものです。カレンダー計算でもカレンダー制作でも、割と無視できない休日のうちのひとつでしょう。

祝日の中でも「天皇誕生日」の仕様がかなり込み入っており、頭痛のタネでもあります。とくに改元(=天皇交代)時の天皇誕生日の変更タイミングが要注意点でもあります。

昭和天皇誕生日:「天皇誕生日」→「みどりの日」→「昭和の日」
平成天皇誕生日:「天皇誕生日」→(2019年には設定されない)
令和天皇誕生日:(2020/2/23より)

とくに、2019年に天皇誕生日が設定されないこと(要注意)。「昭和の日」があっても「平成の日」がないことなど、カレンダー計算および制作時に落とし穴がいっぱいです。

国民の祝日は、カレンダー計算を行ううえでなかなか仕様が込み入っており、仕事(案件)によっては自前で計算するものの、あらかじめ数年分の祝日データを客先から支給されるケースの方が一般的でしょうか。

ただ、あらかじめ計算しておいたデータをもとに処理するという処理方法だけではデータ支給範囲でしかカレンダー計算が行えないため、自前で計算できるようにしておいたほうがよいと考えるものです。

AppleScript名:天皇誕生日の計算.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/08/28
—
–  Copyright © 2019 jp.piyomarusoft, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set dRes to getCurEmpBitrthday(1988) of me
–> 1988/4/29

set dRes to getCurEmpBitrthday(1989) of me
–> 1989/12/23

set dRes to getCurEmpBitrthday(2018) of me
–> 2018/12/23

set dRes to getCurEmpBitrthday(2019) of me
–> false

set dRes to getCurEmpBitrthday(2020) of me
–> 2020/2/23

–天皇誕生日
on getCurEmpBitrthday(targYear)
  –昭和、平成、令和 の誕生日定義
  
set curEmperrorsBirthday to {{"4/29", {1926, 1988}}, {"12/23", {1989, 2018}}, {"2/23", {2020, 9999}}}
  
  
set hitF to false
  
repeat with i in curEmperrorsBirthday
    copy i to {targDate, {beginYear, endYear}}
    
if targYear ≥ beginYear and targYear ≤ endYear then
      set hitF to true
      
exit repeat
    end if
  end repeat
  
  
if hitF = false then
    return false
  end if
  
  
set thisDate to (targYear as string) & "/" & targDate
  
return thisDate
end getCurEmpBitrthday

★Click Here to Open This Script 

Posted in Calendar | Tagged 10.12savvy 10.13savvy 10.14savvy | 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