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

カテゴリー: list

WordPressの指定IDの記事にリンクされているapplescriptからCocoa Classのproperty宣言を抽出

Posted on 7月 30, 2018 by Takaaki Naganoya

WordPressで稼働しているBlog(AppleScriptの穴)の、指定記事IDの本文を取得し、本文内でリンクしているURLのうち指定schemeのものを抽出し、URLリンクされているAppleScriptのソースをデコードしてproperty宣言文のうちCocoa Classの宣言を行っているものを抽出するAppleScriptです。

HTMLReader.frameworkを用いてBlog本文からのリンク抽出、リンクURL抽出を行っています。

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

本Blogで、Tagの運用を変更しようと思い立ち、手作業で修正をはじめました。アプリケーション名のほかにCocoa Class名をTagにしようという試みです。

ただ、数個の記事のTag付け直しを行っただけで「手作業では終わらない」ことが判明。2月に再構築をはじめて1,000本ぐらいの記事をアップしているので、手作業ではとても無理です

本Blogの記事にURLリンクされているAppleScriptソースプログラムを(XML-RPC経由で)AppleScriptから自動で取得し、

その中のproperty宣言文を抽出して、

Cocoa Classの宣言文のみをリストアップして、

Blog記事のTagに自動で指定できないか、と試してみたものです。

現時点で、

  (1)指定Blog記事の本文を取得
  (2)(1)から指定URL SchemeのリンクURLを抽出
  (3)(2)のURL EncodeされているAppleScriptソースをDecode
  (4)property宣言文のみ抽出
  (5)property宣言ラベルがCocoa Classのものかをチェックして抽出

というところまでできています。本プログラムは、BlogのUser NameとPasswordが必要なので、リストのまま動かしてもエラーになり動作しません。同様にWordPressで運用されているBlogがあれば、そちらで試してみるのもよいでしょう。

XML-RPCでWordPressと通信するのには、記事アップロード自動化に使ったFrameworkもありますが、ためしにAppleScript標準搭載のcall xmlrpcコマンドを使ってみました。記事新規投稿コマンドだとクラッシュを起こしますが、この程度の用途ならクラッシュせずに使えるようです。

また、property文の抽出は構文要素を考慮していないため、コメントアウトされているものも拾ってくる可能性があります(単に行頭のproperty宣言文を拾っているだけなので、複数行コメントになっているものは拾われてくることでしょう)。

(*
property NSArray: a reference to current application’s NSArray
property NSString: a reference to current application’s NSString
*)

これを防ぐために、URLリンクされたAppleScriptをデコードした後で、いったんAppleScriptとして構文確認(コンパイル)を実施して、実際のAppleScriptとして評価すべきなのでしょう。

AppleScript名:WordPressの指定IDの記事にリンクされているapplescriptからCocoa Classのproperty宣言を抽出 v2
— Created 2018-07-30 by Takaaki Naganoya
— Modified 2018-07-31 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "HTMLReader" –https://github.com/nolanw/HTMLReader

property |NSURL| : a reference to current application’s |NSURL|
property NSString : a reference to current application’s NSString
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 NSMutableArray : a reference to current application’s NSMutableArray
property NSMutableDictionary : a reference to current application’s NSMutableDictionary
property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding

–PostID
set postID to 3826
set aScheme to "applescript://"

–WordPressの指定Post IDの記事を取得してリンクされているURLからURL Schemeでフィルタして、リンクされているAppleScriptのソースを
–取得し、AS Sourceからproperty宣言文のみ抽出
set pList to getASSouceLinkedInWordPressPost(postID, aScheme) of me
–>  {"property NSBundle : a reference to current application’s NSBundle", "property |NSURL| : a reference to current application’s |NSURL|", "property HTMLDocument : a reference to current application’s HTMLDocument", "property NSMutableDictionary : a reference to current application’s NSMutableDictionary", "property NSPredicate : a reference to current application’s NSPredicate", "property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding", "property NSMutableSet : a reference to current application’s NSMutableSet", "property NSRegularExpressionSearch : a reference to current application’s NSRegularExpressionSearch", "property NSString : a reference to current application’s NSString", "property NSSortDescriptor : a reference to current application’s NSSortDescriptor"}

–property宣言文リストから、propetyがCocoa Classの宣言であるものだけを抽出
set p2List to filterPropertySentenseWhetherCocoaOrNot(pList) of me
–>  {"NSBundle", "HTMLDocument", "NSMutableDictionary", "NSPredicate", "NSMutableSet", "NSString", "NSSortDescriptor"}

on filterPropertySentenseWhetherCocoaOrNot(pList)
  set outList to {}
  
  
repeat with i in pList
    set j to contents of i
    
set j2 to repChar(j, "|", "") of me
    
    
–Parse String Into Words by Space
    
set aTmpStr to (NSString’s stringWithString:j2)
    
set wList to (aTmpStr’s componentsSeparatedByString:" ") as list
    
    
if wList contains {"a", "reference", "to", "current", "application’s"} then
      –通常のクラス名の場合(クラス名以外のpropertyの場合もある)
      
set aTarg to contents of item 2 of wList
      
      
–property値がCocoa Classかどうかを判定    
      
set fRes to searchClassInFrameworks(aTarg) of me
      
      
if fRes is not equal to false then
        set the end of outList to aTarg
      end if
    end if
  end repeat
  
  
return outList
end filterPropertySentenseWhetherCocoaOrNot

–指定クラスがいずれかのCocoa Frameworkに所属しているかを検索
on searchClassInFrameworks(aTarget)
  set aClass to current application’s NSClassFromString(aTarget)
  
if aClass = missing value then return false
  
set theComponenents to (NSBundle’s bundleForClass:aClass)’s bundleURL’s pathComponents()
  
set thePred to NSPredicate’s predicateWithFormat:"pathExtension == ’framework’"
  
set aRes to (theComponenents’s filteredArrayUsingPredicate:thePred)’s firstObject() as list of string or string
  
return aRes
end searchClassInFrameworks

–指定Post IDのWordPress記事から、指定SchemeのURLを抽出し、AS Sourceをdecodeしてproperty行のみ抽出
on getASSouceLinkedInWordPressPost(postID, aScheme)
  set {myUser, myPass} to getAcountData() of me
  
  
tell application "http://piyocast.com/as/xmlrpc.php"
    set wRes to (call xmlrpc {method name:"wp.getPost", parameters:{"1", myUser, myPass, postID as string}})
  end tell
  
set aBody to post_content of wRes –Blog本文
  
  
–記事中でリンクしているURLを取得し、指定のURL Schemeでフィルタする
  
set urlList to filterURLLinksByScheme(aBody, aScheme) of me
  
  
set propList to {}
  
  
repeat with i in urlList
    set j to contents of i
    
set urlRec to parseQueryDictFromURLString(j) of me
    
set tmpScript to (urlRec’s |script|) as string –Get AppleScript Source
    
    
set tList to paragraphs of tmpScript
    
set pList to filterListUsingPredicate(tList, "SELF BEGINSWITH[c] %@", "property") –後方一致
    
    
set propList to propList & pList
  end repeat
  
  
return propList
end getASSouceLinkedInWordPressPost

on filterListUsingPredicate(aList as list, aPredicateStr as string, targStr as string)
  set setKey to current application’s NSMutableSet’s setWithArray:aList
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat_(aPredicateStr, targStr)
  
set aRes to (setKey’s filteredSetUsingPredicate:aPredicate)
  
set bRes to aRes’s allObjects()
  
set cRes to bRes as {list, list of string or string}
  
return cRes
end filterListUsingPredicate

on parseQueryDictFromURLString(aURLStr as string)
  if aURLStr = "" then error "No URL String"
  
  
set aURL to |NSURL|’s URLWithString:aURLStr
  
set aQuery to aURL’s query() –Get Query string part from URL
  
if aQuery’s |length|() = 0 then return false
  
  
set aDict to NSMutableDictionary’s alloc()’s init()
  
set aParamList to (aQuery’s componentsSeparatedByString:"&") as list
  
  
repeat with i in aParamList
    set j to contents of i
    
if length of j > 0 then
      set tmpStr to (NSString’s stringWithString:j)
      
set eList to (tmpStr’s componentsSeparatedByString:"=")
      
set anElement to (eList’s firstObject()’s stringByReplacingPercentEscapesUsingEncoding:(NSUTF8StringEncoding))
      
set aValStr to (eList’s lastObject()’s stringByReplacingPercentEscapesUsingEncoding:(NSUTF8StringEncoding))
      (
aDict’s setObject:aValStr forKey:anElement)
    end if
  end repeat
  
  
return aDict
end parseQueryDictFromURLString

–指定のHTML文字列から、Link URLを抽出し、schemeで再抽出する
on filterURLLinksByScheme(aBody, aScheme)
  set conType to "text/html"
  
  
–HTML文字列をいったんNSDataにしているのは、HTMLReader.frameworkの仕様のため
  
set aData to (current application’s NSString’s stringWithString:aBody)’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aHTML to current application’s HTMLDocument’s documentWithData:aData contentTypeHeader:conType
  
  
set aTextArray to ((aHTML’s nodesMatchingSelector:"a")’s textContent) as list –リンク文字
  
set aLinkList to ((aHTML’s nodesMatchingSelector:"a")’s attributes’s valueForKeyPath:"href") as list –URL文字列
  
  
set outList to {}
  
repeat with i in aLinkList
    set j to contents of i
    
if j begins with aScheme then
      set the end of outList to j
    end if
  end repeat
  
  
return outList
end filterURLLinksByScheme

–文字置換
on repChar(origText as string, targChar as string, repChar as string)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to targChar
  
set tmpList to text items of origText
  
set AppleScript’s text item delimiters to repChar
  
set retText to tmpList as string
  
set AppleScript’s text item delimiters to curDelim
  
return retText
end repChar

on getAcountData()
  return {"xxxxxxxx_xx", "XXXXXXXXXXXXXXXXXXXXXXXX"}
end getAcountData

★Click Here to Open This Script 

Posted in list Network Record URL XML-RPC | Tagged 10.11savvy 10.12savvy 10.13savvy NSArray NSBundle NSString NSURL | Leave a comment

note.muで指定のユーザーのノートを取得する

Posted on 7月 22, 2018 by Takaaki Naganoya

note.muの非公開REST API(でも、みんな知っている)を呼び出して、指定ユーザーのノート(投稿記事)を取得するAppleScriptです。

使い慣れたNSURLConnectionがmacOS 10.11で非推奨APIになって久しく、頻繁に使っているREST API呼び出し処理がいきなり動かなくなるのは困るため、NSURLSessionを用いてREST APIを呼び出すよう徐々に変更しています。

当初、REST APIの呼び出し部分は共通ルーチン化して、さまざまなREST APIを共通ルーチンで処理できるとよいだろうかと思っていました。実際にさまざまなREST APIを呼び出してみると、APIごとに意外なほど癖があって、なかなか「すべてのREST APIの共通処理ルーチン」というところまで共通化する段階までには至っていないところ。

左がNSURLSessionを用いた呼び出し、右がNSURLConnectionを用いた呼び出しを行なったものです。せっかくNSURLSessionを使ってみてはいるものの、同一の処理でもNSURLConnectionの方が40%ぐらい高速です。同一ネットワーク環境(iPhone経由のテザリング接続)でNSURLConnectionが0.4秒ぐらい、NSURLSessionでだいたい0.5から0.7秒といったところ。有線ネットワーク接続だともう少し速度が改善するかもしれません。

NSURLSessionに明示的な同期処理が存在しないため、NSURLSessionが受けわたすdelegateイベントをAppleScript側でループしつつ待っており、NSURLConnectionで素直に同期処理メソッドを呼び出すよりもオーバーヘッドが大きくなっているものと推測しています。

NSURLSessionでREST APIを呼び出すあたりの処理をまるごと独立したFrameworkにでも追い出すとよいのではないか、といったところです。

AppleScript名:(GET)指定のユーザーのノート v2
— Created 2018-06-16 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property |NSURL| : a reference to current application’s |NSURL|
property NSString : a reference to current application’s NSString
property NSURLSession : a reference to current application’s NSURLSession
property NSJSONSerialization : a reference to current application’s NSJSONSerialization
property NSMutableURLRequest : a reference to current application’s NSMutableURLRequest
property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding
property NSURLSessionConfiguration : a reference to current application’s NSURLSessionConfiguration

property retData : missing value

set retData to missing value

set reqURLStr to "https://note.mu/api/v1/notes"
set aRec to {urlname:"140software"} –note ID
set aURL to retURLwithParams(reqURLStr, aRec) of me

set aRESTres to callRestGETAPIAndParseResults(aURL) of me

on callRestGETAPIAndParseResults(reqURLStr)
  set aURL to |NSURL|’s URLWithString:reqURLStr
  
set aRequest to NSMutableURLRequest’s requestWithURL:aURL
  
aRequest’s setHTTPMethod:"GET"
  
aRequest’s setTimeoutInterval:10
  
aRequest’s setValue:"gzip" forHTTPHeaderField:"Content-Encoding"
  
aRequest’s setValue:"application/json; charset=UTF-8" forHTTPHeaderField:"Content-Type"
  
  
set aConfig to NSURLSessionConfiguration’s defaultSessionConfiguration()
  
set aSession to NSURLSession’s sessionWithConfiguration:aConfig delegate:(me) delegateQueue:(missing value)
  
set aTask to aSession’s dataTaskWithRequest:aRequest
  
  
aTask’s resume() –Start URL Session
  
  
repeat 10000 times
    if retData is not equal to missing value then exit repeat
    
current application’s NSThread’s sleepForTimeInterval:("0.001" as real) –delay 0.001
  end repeat
  
  
retData
end callRestGETAPIAndParseResults

on URLSession:tmpSession dataTask:tmpTask didReceiveData:tmpData
  set aStat to (tmpTask’s state()) as list of string or string
  
  
set resStr to NSString’s alloc()’s initWithData:tmpData encoding:(NSUTF8StringEncoding)
  
set jsonString to NSString’s stringWithString:(resStr)
  
  
set jsonData to jsonString’s dataUsingEncoding:(NSUTF8StringEncoding)
  
set aJsonDict to NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value)
  
  
set retData to aJsonDict as list of string or string
end URLSession:dataTask:didReceiveData:

on retURLwithParams(aBaseURL, aRec)
  set aDic to current application’s NSMutableDictionary’s dictionaryWithDictionary:aRec
  
set aKeyList to (aDic’s allKeys()) as list
  
set aValList to (aDic’s allValues()) as list
  
set aLen to length of aKeyList
  
  
set qList to {}
  
repeat with i from 1 to aLen
    set aName to contents of item i of aKeyList
    
set aVal to contents of item i of aValList
    
set the end of qList to (current application’s NSURLQueryItem’s queryItemWithName:aName value:aVal)
  end repeat
  
  
set aComp to current application’s NSURLComponents’s alloc()’s initWithString:aBaseURL
  
aComp’s setQueryItems:qList
  
set aURL to (aComp’s |URL|()’s absoluteString()) as text
  
  
return aURL
end retURLwithParams

★Click Here to Open This Script 

Posted in JSON list REST API URL | Tagged 10.11savvy 10.12savvy 10.13savvy NSJSONSerialization NSMutableURLRequest NSString NSURL NSURLSession NSURLSessionConfiguration NSUTF8StringEncoding | 1 Comment

オープン中のNumbers書類のすべてのシート上のテーブルのデータを連結して新規書類に入れる v2

Posted on 7月 10, 2018 by Takaaki Naganoya

オープン中のNumbers書類のうち最前面のものを対象に、すべてのシート上のテーブル1のデータを連結して新規書類に入れるAppleScriptです。

(↑)Numbers書類中のテーブルのカラム数がすべて同じことが本Scriptの前提条件。

データ結合まではすぐに処理が終わるものの、結合したデータを新規Numbers書類にAppleScriptから順次突っ込むと、データ数の増加にともなって処理時間が大幅に増えるので、そのやり方はやるべきではありません(経験のない素人がやりそうな処理)。

なので、本ScriptではCSVファイルを組み立てて、デスクトップに書き出し、それをNumbersにオープンさせます。

これだと処理は一瞬です。開発環境では、シート9枚&総合計263行のデータを連結してCSVに書き出してNumbers上でオープンするのに1.6秒しかかかりません。

AppleScript名:オープン中のNumbers書類のすべてのシート上のテーブルのデータを連結して新規書類に入れる v2
— Created 2018-07-09 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

script spd
  property allData : {} –Numbersから取得したデータをストアしておく
  
property all2DData : {} –取得したデータを2D Arrayに変換した際にデータをストアしておく
end script

set (allData of spd) to {}
set (all2DData of spd) to {}

set dataWidth to 2

tell application "Numbers"
  tell front document
    set aList to every sheet
    
    
repeat with i in aList
      tell i
        tell table 1
          –テーブル中のセルの値をすべて取得(1D Listで帰ってくる)
          
set aList to value of every cell
          
          
–1D ListをSweep(missing valueの入っているアイテムを削除)
          
set bList to sweep1DList(aList) of me
          
          
–取得してSweepしたデータを連結
          
set (allData of spd) to (allData of spd) & (bList as list)
        end tell
      end tell
    end repeat
    
  end tell
end tell

–1D Listを2D Listに変換
set (all2DData of spd) to conv1DListTo2DList((allData of spd), dataWidth) of me

–まとめたデータをCSVファイルとして書き出し
set aPath to ((path to desktop) as string) & (do shell script "uuidgen") & ".csv"
saveAsCSV((all2DData of spd), aPath) of me

do shell script "sync" –SSDで処理している場合には必要ないが、、、
set anAlias to aPath as alias

–書き出したCSVファイルをNumbersでオープン
tell application "Numbers"
  open anAlias
  
activate
end tell

on sweep1DList(aList)
  load framework
  
return (current application’s SMSForder’s arrayByDeletingBlanksIn:aList) as list
end sweep1DList

on conv1DListTo2DList(aList, groupingNum)
  load framework
  
return (current application’s SMSForder’s subarraysFrom:aList groupedBy:groupingNum |error|:(missing value)) as list
end conv1DListTo2DList

–2D List to CSV file
on saveAsCSV(aList, aPath)
  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
  
  
writeToFile(wholeText, bPath, false) of me
  
end saveAsCSV

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

on repChar(origText as text, targChar as text, repChar as text)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to targChar
  
set tmpList to text items of origText
  
set AppleScript’s text item delimiters to repChar
  
set retText to tmpList as string
  
set AppleScript’s text item delimiters to curDelim
  
return retText
end repChar

★Click Here to Open This Script 

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

CotEditorの最前面のテキストで空行で区切ったブロックを逆順にする

Posted on 7月 8, 2018 by Takaaki Naganoya

CotEditorの最前面のテキスト中で、空行で区切ったブロックを逆順にならべかえるAppleScriptです。

こういう(↑)状態のテキストを、

こういう(↑)状態にならべかえます。

ここでは、わかりやすく空行でブロックを区切っていますが、別のもので区切りを検出してみたり、テキスト全体から自動的にブロック検出をテキストエディタ自体がやってくれるといいのになー、と思っています。

AppleScript名:CotEditorの最前面のテキストで空行で区切ったブロックを逆順にする
— Created 2018-07-07 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

–CotEditorから本文テキストを取得
tell application "CotEditor"
  tell front document
    set aText to contents of it
  end tell
  
set aList to paragraphs of aText
end tell

–空行で区切られたテキストブロックをブロック単位で逆順に組み立てる
set bText to makeRetrunSeparatedStrBlockReversed(aList) of me

–計算結果をCotEditorの本文テキストに書き戻す
tell application "CotEditor"
  tell front document
    set (contents of it) to bText
  end tell
end tell

on makeRetrunSeparatedStrBlockReversed(aList)
  –行ごとにリスト化した1D Listをブロック単位の2D List化
  
set newList to {}
  
set tmpList to {}
  
  
repeat with i in aList
    set j to contents of i
    
if j = "" then
      if tmpList = {} then
        set tmpList to {}
      else
        set the end of newList to tmpList
        
set the end of newList to {}
        
set tmpList to {}
      end if
    else
      set the end of tmpList to j
    end if
  end repeat
  
  
if tmpList is not equal to {} then
    set the end of newList to tmpList
    
set the end of newList to {}
  end if
  
  
set newBList to reverse of newList –ブロックを逆順に
  
  
–2D Listをテキストに
  
set newCList to FlattenList(newBList) of me
  
set resBstr to retStrFromArrayWithDelimiter(newCList, return) of me
  
  
return resBstr
end makeRetrunSeparatedStrBlockReversed

–By Paul Berkowitz
–2009年1月27日 2:24:08:JST
–Re: Flattening Nested Lists
on FlattenList(aList)
  set oldDelims to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to {"????"}
  
set aString to aList as text
  
set aList to text items of aString
  
set AppleScript’s text item delimiters to oldDelims
  
return aList
end FlattenList

–リストを指定デリミタをはさんでテキスト化
on retStrFromArrayWithDelimiter(aList, aDelim)
  set anArray to current application’s NSArray’s arrayWithArray:aList
  
set aRes to anArray’s componentsJoinedByString:aDelim
  
return aRes as text
end retStrFromArrayWithDelimiter

★Click Here to Open This Script 

Posted in list Text | Tagged 10.11savvy 10.12savvy 10.13savvy CotEditor NSArray | Leave a comment

Finder上で選択中のMarkdown書類をファイル名で昇順ソート(A→Z)して、各書類のタイトル見出しを取得する

Posted on 7月 8, 2018 by Takaaki Naganoya

Finder上で選択中のMarkdown書類を取得し、ファイル名で昇順ソート(A→Z)して、各Markdown書類中のタイトルのうち最もレベルの高い(重要な)ものを抽出し、まとめてテキストにしてクリップボードに転送するAppleScriptです。

大量にあるMarkdown書類の本文中から一番重要なタイトルを抽出する作業を……さすがに手作業で行うわけには行かなかったので、AppleScriptを書いて処理してみました。ただし、新規に書いた処理はほとんどなく、既存のルーチンの寄せ合わせで構成しています。

Finder上でMarkdown書類を選択した状態で本Scriptを実行すると(Markdown書類以外は除外して)、AppleScriptでMarkdown書類を読み込んで(Markdown書類がUTF-8固定なのでUTF-8を指定して読み込み)、正規表現で書類中のタイトルを抽出し、重要なタイトル(#の個数が少ない)をピックアップ。これをすべての書類について行います。

処理結果をクリップボードに転送します。

最終的には、(手作業で加工して)このようになります。

若干の手作業は発生してしまいますが、このScriptを組まなかったら、とてもその手作業を行う気も起こらなかったわけで、、、

AppleScript名:Finder上で選択中のMarkdown書類をファイル名で昇順ソート(A→Z)して、各書類のタイトル見出しを取得する
— Created 2018-06-26 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Quartz"
use mdLib : script "Metadata Lib" version "1.0.0"
use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

property |NSURL| : a reference to current application’s |NSURL|
property NSArray : a reference to current application’s NSArray
property NSString : a reference to current application’s NSString
property SMSForder : a reference to current application’s SMSForder
property NSIndexSet : a reference to current application’s NSIndexSet
property NSPredicate : a reference to current application’s NSPredicate
property NSMutableSet : a reference to current application’s NSMutableSet
property NSFileManager : a reference to current application’s NSFileManager
property NSCountedSet : a reference to current application’s NSCountedSet
property NSURLPathKey : a reference to current application’s NSURLPathKey
property NSMutableArray : a reference to current application’s NSMutableArray
property NSURLNameKey : a reference to current application’s NSURLNameKey
property NSSortDescriptor : a reference to current application’s NSSortDescriptor
property NSURLIsPackageKey : a reference to current application’s NSURLIsPackageKey
property NSRegularExpression : a reference to current application’s NSRegularExpression
property NSURLIsDirectoryKey : a reference to current application’s NSURLIsDirectoryKey
property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey
property NSURLContentModificationDateKey : a reference to current application’s NSURLContentModificationDateKey
property NSRegularExpressionAnchorsMatchLines : a reference to current application’s NSRegularExpressionAnchorsMatchLines
property NSDirectoryEnumerationSkipsHiddenFiles : a reference to current application’s NSDirectoryEnumerationSkipsHiddenFiles
property NSRegularExpressionDotMatchesLineSeparators : a reference to current application’s NSRegularExpressionDotMatchesLineSeparators

load framework

–set inFiles to (choose file of type {"pdf"} with prompt "Choose your PDF files:" with multiple selections allowed)
tell application "Finder"
  set inFiles to selection as alias list
end tell

if inFiles = {} then return

–指定のAlias listのうちMarkdown書類のみ抽出
set filRes1 to filterAliasListByUTI(inFiles, "net.daringfireball.markdown") of me

–指定のPOSIX path listから、各Markdown書類中の一番重要な見出しを抽出して返す
set tRes to listTitlesFromMarkdownDocPathList(filRes1) of me

–取得したタイトル一覧リストをテキストに変換
set t2Res to retStrFromArrayWithDelimiter(tRes, return) of me

–クリップボードに結果を転送
set the clipboard to t2Res

on listTitlesFromMarkdownDocPathList(inFiles)
  set outList to {}
  
set inFilesSorted to my filesInListSortAscending(inFiles)
  
  
repeat with i in inFilesSorted
    –POSIX pathからaliasにパス変換してテキスト読み込み
    
set j to POSIX file (contents of i)
    
set jj to j as alias
    
set aStr to (read jj as «class utf8»)
    
    
set aList to retHeaders(aStr) of me –Markdown書類中の見出しをリストアップ
    
–>  {​​​​​{​​​​​​​1, ​​​​​​​" 2008/3/9 5桁の乱数を生成"​​​​​}​​​}
    
    
if aList is not equal to {} then
      –2D Listの昇順ソート
      
set sortIndexes to {0} –Key Item id: begin from 0
      
set sortOrders to {true} –ascending = true
      
set sortTypes to {"compare:"}
      
set resList to (current application’s SMSForder’s subarraysIn:(aList) sortedByIndexes:sortIndexes ascending:sortOrders sortTypes:sortTypes |error|:(missing value)) as list
      
      
set aCon to contents of second item of first item of resList
      
set the end of outList to aCon
    end if
  end repeat
  
return outList
end listTitlesFromMarkdownDocPathList

on filesInListSortAscending(aliasList as list)
  set cList to {}
  
repeat with i in aliasList
    set j to contents of i
    
set aFileName to ((current application’s NSString’s stringWithString:j)’s valueForKeyPath:"lastPathComponent")
    
set the end of cList to {fileName:aFileName, pathDat:j}
  end repeat
  
  
set aResList to sortRecListByLabel(cList, "fileName", true) of me –昇順ソート
  
set bResList to (aResList’s valueForKeyPath:"pathDat") as list of string or string
  
return bResList
end filesInListSortAscending

–Alias listから指定UTIに含まれるものをPOSIX pathのリストで返す
on filterAliasListByUTI(aList, targUTI)
  set newList to {}
  
repeat with i in aList
    set j to POSIX path of i
    
set tmpUTI to my retUTIfromPath(j)
    
set utiRes to my filterUTIList({tmpUTI}, targUTI)
    
if utiRes is not equal to {} then
      set the end of newList to j
    end if
  end repeat
  
return newList
end filterAliasListByUTI

–指定の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

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

–リストに入れたレコードを、指定の属性ラベルの値でソート
on sortRecListByLabel(aRecList as list, aLabelStr as string, ascendF as boolean)
  set aArray to current application’s NSArray’s arrayWithArray:aRecList
  
  
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
  
return sortedArray
end sortRecListByLabel

–見出し抽出用サブルーチン群
on retHeaders(aCon)
  set tList to {}
  
set regStr to "^#{1,6}[^#]*?$"
  
  
set headerList to my findPattern:regStr inString:aCon
  
repeat with i in headerList
    set j to contents of i
    
set regStr2 to "^#{1,6}[^#]*?"
    
set headerLevel to length of first item of (my findPattern:regStr2 inString:j)
    
set the end of tList to {headerLevel, text (headerLevel + 1) thru -1 in j}
  end repeat
  
  
return tList
end retHeaders

on findPattern:thePattern inString:theString
  set theOptions to ((NSRegularExpressionDotMatchesLineSeparators) as integer) + ((NSRegularExpressionAnchorsMatchLines) as integer)
  
set theRegEx to NSRegularExpression’s regularExpressionWithPattern:thePattern options:theOptions |error|:(missing value)
  
set theFinds to theRegEx’s matchesInString:theString options:0 range:{location:0, |length|:length of theString}
  
set theFinds to theFinds as list — so we can loop through
  
set theResult to {} — we will add to this
  
set theNSString to NSString’s stringWithString:theString
  
repeat with i from 1 to count of items of theFinds
    set theRange to (item i of theFinds)’s range()
    
set end of theResult to (theNSString’s substringWithRange:theRange) as string
  end repeat
  
return theResult
end findPattern:inString:

–リストを指定デリミタをはさんでテキスト化
on retStrFromArrayWithDelimiter(aList, aDelim)
  set anArray to current application’s NSArray’s arrayWithArray:aList
  
set aRes to anArray’s componentsJoinedByString:aDelim
  
return aRes as list of string or string
end retStrFromArrayWithDelimiter

★Click Here to Open This Script 

Posted in file list Markdown regexp Sort Text | Tagged 10.11savvy 10.12savvy 10.13savvy Finder NSArray NSCountedSet NSDirectoryEnumerationSkipsHiddenFiles NSFileManager NSIndexSet NSMutableArray NSMutableSet NSPredicate NSRegularExpression NSRegularExpressionAnchorsMatchLines NSRegularExpressionDotMatchesLineSeparators NSSortDescriptor NSString NSURL NSURLContentModificationDateKey NSURLIsDirectoryKey NSURLIsPackageKey NSURLNameKey NSURLPathKey NSURLTypeIdentifierKey | 3 Comments

NSCountedSetでヒストグラム計算、指定単語リストを削除

Posted on 7月 6, 2018 by Takaaki Naganoya

指定の単語リストから登場頻度の計算(ヒストグラム)を行い、指定単語リストに入っているものについては除外するAppleScriptです。

指定のPDFからURLリンクを抽出し、そのリンクURLをデコードしてAppleScriptのURLリンクからソーステキストを取得し、単語ごとにparseして集計してタグクラウドのRTFを出力するAppleScriptを作成したときに使用したものです。

単に、プログラムリストをparseしてタグクラウドを作成しただけでは、あまり本質(ノイズ要素を除外した分析したい対象のデータ)が見えてきませんでした。

変数名やコマンドなどを除外したかったので、これら(分析対象外のデータ=ノイズ)を集計時に除外するという処理を加えてみたものです。

AppleScript名:NSCountedSetでヒストグラム計算、指定単語リストを削除
— Created 2018-07-06 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set theList to {"set", "set", "set", "tell", "application", "application", "Finder", "Finder", "Safari"}
set exList to {"Finder", "Safari"}
set aRes to wordsCountWithRemovingWordList(theList, exList) of me
–>  {​​​​​{​​​​​​​theKey:"set", ​​​​​​​theCount:3​​​​​}, ​​​​​{​​​​​​​theKey:"application", ​​​​​​​theCount:2​​​​​}, ​​​​​{​​​​​​​theKey:"tell", ​​​​​​​theCount:1​​​​​}​​​}

on wordsCountWithRemovingWordList(theList as list, excludeWordList as list)
  set theCountedSet to current application’s NSCountedSet’s alloc()’s initWithArray:theList
  
  
set newArray to current application’s NSMutableArray’s new()
  
set objList to (theCountedSet’s allObjects()) as list
  
  
repeat with i in objList
    set j to contents of i
    
if j is not in excludeWordList then
      (newArray’s addObject:{theKey:j, theCount:(theCountedSet’s countForObject:j)})
    end if
  end repeat
  
  
return newArray as list of string or string
end wordsCountWithRemovingWordList

★Click Here to Open This Script 

Posted in list Record Text | Tagged 10.11savvy 10.12savvy 10.13savvy NSCountedSet NSMutableArray | Leave a comment

日付テキストを年単位で集計

Posted on 6月 29, 2018 by Takaaki Naganoya

yyyy-MM-dd HH:mm:ss形式の日付テキストをdateオブジェクトに変換して日付を年単位で集計するAppleScriptです。

Blog Archiveのデータベースのダンプテキストを読み取って、年別の投稿記事本数の集計を行うために作成しました(といっても、既存のルーチンを組み合わせただけです)。

AppleScript名:日付テキストを年単位で集計
— Created 2018-06-28 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property NSArray : a reference to current application’s NSArray
property NSString : a reference to current application’s NSString
property NSLocale : a reference to current application’s NSLocale
property NSDictionary : a reference to current application’s NSDictionary
property NSCountedSet : a reference to current application’s NSCountedSet
property NSMutableArray : a reference to current application’s NSMutableArray
property NSSortDescriptor : a reference to current application’s NSSortDescriptor
property NSDateFormatter : a reference to current application’s NSDateFormatter

set aList to {"2006-06-27 02:38:52", "2008-03-09 19:08:05", "2008-03-09 19:29:29"}
set aRes to totalDateStrByYear(aList, "yyyy-MM-dd HH:mm:ss") of me
–> {{aCount:1, aKey:2006}, {aCount:2, aKey:2008}}

–日付テキストを年単位で集計
on totalDateStrByYear(aList, strFormat)
  set theCountedSet to NSCountedSet’s |set|()
  
set newArray to NSMutableArray’s new()
  
  
repeat with i in aList
    set postDate to dateFromStringWithDateFormat(i, strFormat) of me –日付テキストをDate Objectに変換
    
set yearStr to (year of postDate) –「年」の数字
    (
newArray’s addObject:yearStr)
  end repeat
  
  
set resArray to countItemsByItsAppearance(newArray) of me
  
set bList to sortRecListByLabel(resArray, "aKey", true) of me –昇順ソート
  
return bList
end totalDateStrByYear

–日付文字列からdate objectを作成する
on dateFromStringWithDateFormat(dateString, dateFormat)
  set dStr to NSString’s stringWithString:dateString
  
set dateFormatStr to NSString’s stringWithString:dateFormat
  
  
set aDateFormatter to NSDateFormatter’s alloc()’s init()
  
aDateFormatter’s setDateFormat:dateFormatStr
  
aDateFormatter’s setLocale:(NSLocale’s alloc()’s initWithLocaleIdentifier:"en_US_POSIX")
  
  
set aDestDate to (aDateFormatter’s dateFromString:dStr)
  
  
return aDestDate as list of string or string
end dateFromStringWithDateFormat

–登場頻度でリストを集計する
on countItemsByItsAppearance(aList)
  set aSet to NSCountedSet’s alloc()’s initWithArray:aList
  
set bArray to 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:(NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{"aKey", "aCount"})
  end repeat
  
  
return bArray
end countItemsByItsAppearance

–リストに入れたレコードを、指定の属性ラベルの値でソート
on sortRecListByLabel(aRecList as list, aLabelStr as string, ascendF as boolean)
  set aArray to NSArray’s arrayWithArray:aRecList
  
  
set sortDesc to NSSortDescriptor’s alloc()’s initWithKey:aLabelStr ascending:ascendF
  
set sortDescArray to NSArray’s arrayWithObjects:sortDesc
  
set sortedArray to aArray’s sortedArrayUsingDescriptors:sortDescArray
  
  
set bList to (sortedArray) as list of string or string
  
return bList
end sortRecListByLabel

★Click Here to Open This Script 

Posted in Calendar list | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

Numbersのアクティブシート上の表の行数をデータに合わせる

Posted on 6月 13, 2018 by Takaaki Naganoya

Numbersの最前面の書類の選択中のシート(アクティブシート)上の「表」の行数をデータに合わせて変更するAppleScriptです。


▲Before


▲After

表データ上の空白部分を末尾(下)から先頭(上)に向かってサーチし、空白ではない箇所を見つけるまで繰り返します。

AppleScript名:Numbersのアクティブシート上の表の行数をデータに合わせる
— Created 2018-06-12 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

set tCount to getTableCount() of me

repeat with tableID from 1 to tCount
  
  
–Numbersからデータを取得する
  
set aList to getDataFromNumbersDoc(tableID) of me
  
if aList = false then error "No Data in table " & (tableID as string)
  
  
–Numbersの対象の表の情報を取得
  
set aWidth to getColumnCount(tableID) of me
  
set aHeaderCount to getHeaderCount(tableID) of me
  
set aFooterCount to getFooterCount(tableID) of me
  
  
–Numbersから取得した2D Listのデータからデータの末尾を見つける
  
set aDataRowCount to findDataEnd(aWidth, aHeaderCount, aFooterCount, aList) of me
  
  
tell application "Numbers"
    tell front document
      tell active sheet
        tell table tableID
          set row count to aDataRowCount
        end tell
      end tell
    end tell
  end tell
  
end repeat

–Numbersでオープン中の書類の選択中のシートの表1からデータを取得して2D Listに
on getDataFromNumbersDoc(tableNum as integer)
  
  
load framework
  
  
tell application "Numbers"
    if (count every document) = 0 then return false
    
    
tell front document
      if (count every sheet) = 0 then return false
      
      
tell active sheet
        tell table tableNum
          set colCount to column count
          
set rowCount to row count
          
set headerCount to header row count
          
set footerCount to footer row count
          
          
set dList to value of every cell of cell range
        end tell
      end tell
      
    end tell
  end tell
  
  
–Convert 1D List to 2D List
  
set bList to (current application’s SMSForder’s subarraysFrom:dList groupedBy:colCount |error|:(missing value)) as list
  
set sItem to 1 + headerCount
  
set eItem to rowCount – footerCount
  
set cList to items sItem thru eItem of bList
  
  
return cList
  
end getDataFromNumbersDoc

on getTableCount()
  tell application "Numbers"
    set dCount to count every document
    
if dCount = 0 then error "Numbers: There is No Document"
    
    
tell front document
      tell active sheet
        return (count every table)
      end tell
    end tell
  end tell
end getTableCount

on getHeaderCount(tableID as integer)
  tell application "Numbers"
    tell front document
      tell active sheet
        tell table tableID
          return (header row count)
        end tell
      end tell
    end tell
  end tell
end getHeaderCount

on getFooterCount(tableID as integer)
  tell application "Numbers"
    tell front document
      tell active sheet
        tell table tableID
          return (footer row count)
        end tell
      end tell
    end tell
  end tell
end getFooterCount

on getColumnCount(tableID as integer)
  tell application "Numbers"
    tell front document
      tell active sheet
        tell table tableID
          return (column count)
        end tell
      end tell
    end tell
  end tell
end getColumnCount

–Numbersから取得した2D Arrayのデータ末尾を見つける(ただし、高速化処理を一切していないのでデータ数が数千件を超えると遅くなる)
on findDataEnd(aWidth as integer, aHeaderCount as integer, aFooterCount as integer, aList as list)
  set rAList to reverse of aList –get reverse order list
  
  
set anItem to {}
  
repeat aWidth times
    set the end of anItem to missing value
  end repeat
  
  
set aCount to length of aList
  
set hitF to false
  
  
repeat with i in rAList
    set j to contents of i
    
if j is not equal to anItem then
      set hitF to true
      
exit repeat
    end if
    
set aCount to aCount – 1
  end repeat
  
  
if hitF = false then return false –すべて空(missing value)だった場合には処理打ち切り
  
  
return aCount + aHeaderCount + aFooterCount
end findDataEnd

★Click Here to Open This Script 

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

Numbersで選択範囲のセルのデータを取得して重複データを抽出

Posted on 6月 7, 2018 by Takaaki Naganoya

Numbersの表データの選択範囲のセルのデータを取得し、重複データがあれば重複データのみ表示するAppleScriptです。

# NumbersというApple社製の表計算アプリケーションを操作する話であって、宝くじの話ではありません。また、本BlogはScriptでMac上のアプリケーションやOS内のサービスを呼び出して処理する話を紹介しているものであって、単に画面上から削除する方法を紹介するものではありません。また、データのユニーク化処理ができないわけがありません。とっくの昔に書いています。

macOS標準装備のScript Menuに入れて便利に使っています。Numbers上の選択範囲内に重複データがあれば、ダイアログでデータを表示します。

AppleScript名:Numbersで選択範囲のセルのデータを取得して重複データを抽出
— Created 2018-01-13 by Takaaki Naganoya
— Modified 2018-06-06 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property NSCountedSet : a reference to current application’s NSCountedSet

script spd
  property uniqList : {}
end script

set (uniqList of spd) to {}

tell application "Numbers"
  tell front document
    tell active sheet
      try
        set theTable to first table whose class of selection range is range
      on error
        display notification "Numbers: There is no selection"
        
return
      end try
      
      
tell theTable
        set (uniqList of spd) to value of cells of selection range
      end tell
    end tell
  end tell
end tell

if (uniqList of spd) = {} then
  display notification "Numbers: There is no selection"
  
return
end if

set aRes to returnDuplicatesOnly(uniqList of spd) of me
if aRes is not equal to {} then
  choose from list aRes with prompt "Duplicated Data:"
else
  display notification "No Duplicated Data"
end if

–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 | Tagged 10.11savvy 10.12savvy 10.13savvy Numbers | Leave a comment

Tag CloudっぽいRTFの作成

Posted on 6月 6, 2018 by Takaaki Naganoya

指定のrecord in listからTag CloudっぽいRTFファイルをデスクトップに生成するAppleScriptです。

以前からTag Cloudを出力するフレームワークやObjective-Cのプログラムを探していたのですが、なかなか具合のいいものがありませんでした。

動作原理を考えたら割と簡単そうだったので、仕方なく自分で作ることに。

作ってみて「そんなに難しくない」ことはわかりましたが、まだまだ自分が望むようなものにはなっていません。とりあえず「まあそんなもんだよね」という程度のものです。

set tagList to {{tagname:”AirServer”, tagcount:2}, {tagname:”App Store”, tagcount:1}, {tagname:”Calendar”, tagcount:3}, {tagname:”Contacts”, tagcount:1}, {tagname:”CotEditor”, tagcount:27}, {tagname:”Dictionary”, tagcount:9}, {tagname:”Dock”, tagcount:7}, {tagname:”Evernote”, tagcount:2}, {tagname:”Finder”, tagcount:20}, {tagname:”HelpViewer”, tagcount:2}, {tagname:”HoudahSpot”, tagcount:1}, {tagname:”iBooks”, tagcount:1}, {tagname:”Image Events”, tagcount:1}, {tagname:”iTunes”, tagcount:12}, {tagname:”JeditΩ”, tagcount:3}, {tagname:”Keynote”, tagcount:14}, {tagname:”Mac Blu-ray Player”, tagcount:1}, {tagname:”MacDown”, tagcount:3}, {tagname:”Mail”, tagcount:6}, {tagname:”Maps”, tagcount:3}, {tagname:”mi”, tagcount:2}, {tagname:”Numbers”, tagcount:8}, {tagname:”Pages”, tagcount:2}, {tagname:”Preview.app”, tagcount:2}, {tagname:”QuickTime Player”, tagcount:8}, {tagname:”Reminders”, tagcount:1}, {tagname:”Safari”, tagcount:13}, {tagname:”Script Debugger”, tagcount:1}, {tagname:”Script Editor”, tagcount:7}, {tagname:”Sorting”, tagcount:5}, {tagname:”Spell check”, tagcount:3}, {tagname:”System Events”, tagcount:6}, {tagname:”Terminal”, tagcount:4}, {tagname:”TextEdit”, tagcount:12}, {tagname:”Twitter”, tagcount:1}, {tagname:”Xcode”, tagcount:2}}

という入力から、

というタグクラウドのRTFをデスクトップに書き出します。処理時間は開発環境(MacBook Pro Retina 2012 Core i7 2.66GHz)で0.08秒ぐらいです。

本当は、こんな1次元で連続した内容ではなく、2次元で各タグを分離したオブジェクトとして平面上に配置し、かつ、大きな文字の内容を中心部に配置するとか、間を詰めるために縦方向に回転させたタグも入れるとか、そういう感じの処理を(自動で)行いたいところなので、このレベルだと「ただタグとして並んでいるだけ」で満足できません。

最終的には、日本語のテキストを形態素解析して固有名詞のみ抽出し、出現頻度の高いものをタグクラウドで並べることで内容を把握しやすくする、といった処理を行いたいところです。

AppleScript名:Tag CloudっぽいRTFの作成
— Created 2018-06-06 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSFont : a reference to current application’s NSFont
property NSUUID : a reference to current application’s NSUUID
property NSColor : a reference to current application’s NSColor
property NSString : a reference to current application’s NSString
property Board2D : a reference to current application’s Board2D
property Pathfinder : a reference to current application’s Pathfinder
property NSDictionary : a reference to current application’s NSDictionary
property NSLiteralSearch : a reference to current application’s NSLiteralSearch
property NSMutableArray : a reference to current application’s NSMutableArray
property NSFontAttributeName : a reference to current application’s NSFontAttributeName
property NSMutableAttributedString : a reference to current application’s NSMutableAttributedString
property NSForegroundColorAttributeName : a reference to current application’s NSForegroundColorAttributeName
property NSDocumentTypeDocumentAttribute : a reference to current application’s NSDocumentTypeDocumentAttribute

set tagList to {{tagname:"AirServer", tagcount:2}, {tagname:"App Store", tagcount:1}, {tagname:"Calendar", tagcount:3}, {tagname:"Contacts", tagcount:1}, {tagname:"CotEditor", tagcount:27}, {tagname:"Dictionary", tagcount:9}, {tagname:"Dock", tagcount:7}, {tagname:"Evernote", tagcount:2}, {tagname:"Finder", tagcount:20}, {tagname:"HelpViewer", tagcount:2}, {tagname:"HoudahSpot", tagcount:1}, {tagname:"iBooks", tagcount:1}, {tagname:"Image Events", tagcount:1}, {tagname:"iTunes", tagcount:12}, {tagname:"JeditΩ", tagcount:3}, {tagname:"Keynote", tagcount:14}, {tagname:"Mac Blu-ray Player", tagcount:1}, {tagname:"MacDown", tagcount:3}, {tagname:"Mail", tagcount:6}, {tagname:"Maps", tagcount:3}, {tagname:"mi", tagcount:2}, {tagname:"Numbers", tagcount:8}, {tagname:"Pages", tagcount:2}, {tagname:"Preview.app", tagcount:2}, {tagname:"QuickTime Player", tagcount:8}, {tagname:"Reminders", tagcount:1}, {tagname:"Safari", tagcount:13}, {tagname:"Script Debugger", tagcount:1}, {tagname:"Script Editor", tagcount:7}, {tagname:"Sorting", tagcount:5}, {tagname:"Spell check", tagcount:3}, {tagname:"System Events", tagcount:6}, {tagname:"Terminal", tagcount:4}, {tagname:"TextEdit", tagcount:12}, {tagname:"Twitter", tagcount:1}, {tagname:"Xcode", tagcount:2}}

set targFontName to "Courier-Bold" –PostScript Name

set tagArray to current application’s NSMutableArray’s arrayWithArray:tagList
set aMax to (tagArray’s valueForKeyPath:"@max.tagcount") as list of string or string –as anything
set aMin to (tagArray’s valueForKeyPath:"@min.tagcount") as list of string or string –as anything

set strList to tagArray’s valueForKey:"tagname"
set strAll to retArrowText(strList, " ") of me
set strAll to " " & strAll & " "

set anAttr to current application’s NSMutableAttributedString’s alloc()’s initWithString:strAll

repeat with i in tagList
  set aName to (tagname of i) as string
  
set aNum to (tagcount of i) as number
  
if aNum > (aMax * 0.8) then
    set aFontSize to 48
    
set aColor to current application’s NSColor’s redColor()
  else if aNum > (aMax * 0.6) then
    set aFontSize to 36
    
set aColor to current application’s NSColor’s orangeColor()
  else if aNum > (aMax * 0.4) then
    set aFontSize to 22
    
set aColor to current application’s NSColor’s greenColor()
  else
    set aFontSize to 16
    
set aColor to current application’s NSColor’s blackColor()
  end if
  
  
set aFont to (current application’s NSFont’s fontWithName:targFontName |size|:aFontSize)
  
  
–Caution: Call by Reference
  
markCharOfAttributedString(anAttr, strAll, " " & aName & " ", aColor, aFont) of me
  
end repeat

–結果のRTFをデスクトップ上に書き出す。ファイル名はUUID.rtf
set targFol to current application’s NSHomeDirectory()’s stringByAppendingPathComponent:"Desktop"
set aRes to my saveStyledTextAsRTF(targFol, anAttr)

–指定のAttributed String内で指定文字列が含まれる箇所に指定の色をつける(結果はメイン側に参照渡し)
on markCharOfAttributedString(anAttr, origStr, aTargStr, aColor, aFont)
  set rList to searchWordWithRange(origStr, aTargStr) of me
  
repeat with ii in rList
    (anAttr’s addAttribute:(NSForegroundColorAttributeName) value:aColor range:ii)
    (
anAttr’s addAttribute:(NSFontAttributeName) value:aFont range:ii)
  end repeat
end markCharOfAttributedString

–指定の文字列をAttributed Stringに変換して任意のフォントを一括指定
on changeAttrStrsFontAttribute(aStr, aFontPSName, aFontSize)
  set tmpAttr to NSMutableAttributedString’s alloc()’s initWithString:aStr
  
set aRange to current application’s NSMakeRange(0, tmpAttr’s |length|())
  
set aVal1 to NSFont’s fontWithName:aFontPSName |size|:aFontSize
  
tmpAttr’s beginEditing()
  
tmpAttr’s addAttribute:(NSFontAttributeName) value:aVal1 range:aRange
  
tmpAttr’s endEditing()
  
return tmpAttr
end changeAttrStrsFontAttribute

–スタイル付きテキストを指定フォルダ(POSIX path)にRTFで書き出し
on saveStyledTextAsRTF(targFol, aStyledString)
  set bstyledLength to aStyledString’s |string|()’s |length|()
  
set bDict to NSDictionary’s dictionaryWithObject:"NSRTFTextDocumentType" forKey:(NSDocumentTypeDocumentAttribute)
  
set bRTF to aStyledString’s RTFFromRange:(current application’s NSMakeRange(0, bstyledLength)) documentAttributes:bDict
  
  
set theName to (NSUUID’s UUID()’s UUIDString())
  
set thePath to NSString’s stringWithString:targFol
  
set thePath to (thePath’s stringByAppendingPathComponent:theName)’s stringByAppendingPathExtension:"rtf"
  
return (bRTF’s writeToFile:thePath atomically:true) as boolean
end saveStyledTextAsRTF

–指定テキストデータ(atargText)内に、指定文字列(aSearchStr)が含まれる範囲情報(NSRange)をすべて取得する
on searchWordWithRange(aTargText, aSearchStr)
  set aStr to NSString’s stringWithString:aTargText
  
set bStr to NSString’s stringWithString:aSearchStr
  
set hitArray to NSMutableArray’s alloc()’s init()
  
set cNum to (aStr’s |length|()) as integer
  
  
set aRange to current application’s NSMakeRange(0, cNum)
  
  
repeat
    set detectedRange to aStr’s rangeOfString:bStr options:NSLiteralSearch range:aRange
    
set aLoc to (detectedRange’s location)
    
–CAUTION !!!! Sometimes aLoc returns not NSNotFound (-1) but a Very large number
    
if (aLoc > 9.999999999E+9) or (aLoc = (current application’s NSNotFound)) then exit repeat
    
    
hitArray’s addObject:detectedRange
    
    
set aNum to aLoc as integer
    
set bNum to (detectedRange’s |length|) as integer
    
    
set aRange to current application’s NSMakeRange(aNum + bNum, cNum – (aNum + bNum))
  end repeat
  
  
return hitArray
end searchWordWithRange

–リストを指定デリミタをはさんでテキスト化
on retStrFromArrayWithDelimiter(aList, aDelim)
  set anArray to current application’s NSArray’s arrayWithArray:aList
  
set aRes to anArray’s componentsJoinedByString:aDelim
  
return aRes as list of string or string
end retStrFromArrayWithDelimiter

on retArrowText(aList, aDelim) –自分のASでよく使うハンドラ名称なので、同じものを用意
  return my retStrFromArrayWithDelimiter(aList, aDelim)
end retArrowText

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

★Click Here to Open This Script 

Posted in list Record RTF Text | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

各TTSの名前とバージョン情報を取得

Posted on 5月 28, 2018 by Takaaki Naganoya

OSにインストールされている各TTS(Text To Speech)の名称一覧とバージョン情報を取得するAppleScriptです。

AppleScriptのsayコマンドには音声を指定する機能が用意されていますが、その一方でOSにインストールされているTTS音声の一覧を取得する機能がないため、このようにしてTTS音声名称を取得したり、対応言語(英語とか日本語とか)でしぼりこみを行なって指定言語のテキスト読み上げに必要なTTS音声が存在しているかといった判定を行います。

各TTS Voiceには、

{​​​​​​​VoiceName:”Vicki”, ​​​​​​​VoiceLocaleIdentifier:”en_US”, ​​​​​​​VoiceIndividuallySpokenCharacters:{{….}}, VoiceDemoText:”Isn’t it nice to have a computer that will talk to you?”, ​​​​​​​VoiceSupportedCharacters:{​​​​​​​​​{…}}, VoiceShowInFullListOnly:1, ​​​​​​​VoiceGender:”VoiceGenderFemale”, ​​​​​​​VoiceVersion:”3.6″, ​​​​​​​VoiceAge:35, ​​​​​​​VoiceIdentifier:”com.apple.speech.synthesis.voice.Vicki”, ​​​​​​​VoiceRelativeDesirability:5100, ​​​​​​​VoiceLanguage:”en-US”​​​​​}

のような属性情報があり、このVoiceNameとVoiceVersionを求めています。

Japanese TTS VoiceのOtoya v6.3.1とKyoko v6.3.1でも、あいかわらず「捥げる」「もげる」を正しく読み上げられない(「げる」、「もげ」になる)バグは治っていません(これを確認するのが本Scriptの目的です)。

AppleScript名:各TTSの名前とバージョン情報を取得
— Created 2015-08-25 by Takaaki Naganoya
— Modified 2015-08-26 by Shane Stanley, Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

set v1Res to getVoiceNamesAndVers()
–>  {{"Agnes", "3.6"}, {"Albert", "3.6"}, {"Alex", "2.0.36"}, {"Alice", "6.1.1"}, {"Allison", "6.3.1"}, {"Alva", "6.1.1"}, {"Amelie", "6.1.1"}, {"Anna", "6.3.1"}, {"Audrey", "6.3.1"}, {"Ava", "6.3.1"}, {"Bad News", "3.6"}, {"Bahh", "3.6"}, {"Bells", "3.6"}, {"Boing", "3.6"}, {"Bruce", "3.6"}, {"Bubbles", "3.6"}, {"Carmit", "6.1.1"}, {"Cellos", "3.6"}, {"Damayanti", "6.1.1"}, {"Daniel", "6.3.1"}, {"Deranged", "3.6"}, {"Diego", "6.1.1"}, {"Ellen", "6.1.1"}, {"Emily", "2.0.3"}, {"Fiona", "6.1.1"}, {"Fred", "3.6"}, {"Good News", "3.6"}, {"Hysterical", "3.6"}, {"Ioana", "6.1.1"}, {"Jill", "2.0.3"}, {"Joana", "6.1.1"}, {"Jorge", "6.1.1"}, {"Juan", "6.1.1"}, {"Junior", "3.6"}, {"Kanya", "6.1.1"}, {"Karen", "6.3.1"}, {"Kate", "6.3.1"}, {"Kathy", "3.6"}, {"Kyoko", "6.3.1"}, {"Laura", "6.1.1"}, {"Lee", "6.3.1"}, {"Lekha", "6.1.1"}, {"Luca", "6.1.1"}, {"Luciana", "6.1.1"}, {"Maged", "6.1.1"}, {"Mariska", "6.1.1"}, {"Mei-Jia", "6.1.1"}, {"Melina", "6.1.1"}, {"Milena", "6.1.1"}, {"Moira", "6.1.1"}, {"Monica", "6.1.1"}, {"Nora", "6.1.1"}, {"Otoya", "6.3.1"}, {"Paulina", "6.1.1"}, {"Pipe Organ", "3.6"}, {"Princess", "3.6"}, {"Ralph", "3.6"}, {"Samantha", "6.3.1"}, {"Sara", "6.1.1"}, {"Satu", "6.1.1"}, {"Serena", "6.3.1"}, {"Sin-ji", "6.1.1"}, {"Tessa", "6.1.1"}, {"Thomas", "6.1.1"}, {"Ting-Ting", "6.3.1"}, {"Tom", "6.3.1"}, {"Trinoids", "3.6"}, {"Veena", "6.1.1"}, {"Vicki", "3.6"}, {"Victoria", "3.6"}, {"Whisper", "3.6"}, {"Xander", "6.1.1"}, {"Yelda", "6.1.1"}, {"Yuna", "6.3.1"}, {"Yuri", "6.1.1"}, {"Zarvox", "3.6"}, {"Zosia", "6.1.1"}, {"Zuzana", "6.1.1"}}

–Get TTS Voice names and versions
on getVoiceNamesAndVers()
  set aList to {}
  
  
set nameList to (current application’s NSSpeechSynthesizer’s availableVoices()) as list
  
repeat with i in nameList
    set j to contents of i
    
set aDic to ((current application’s NSSpeechSynthesizer’s attributesForVoice:j))
    
set aName to (aDic’s VoiceName) as string
    
set aVer to (aDic’s VoiceVersion) as string
    
set the end of aList to {aName, aVer}
  end repeat
  
  
return aList as list
end getVoiceNamesAndVers

★Click Here to Open This Script 

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

指定のリスト中の指定要素が占める割合をパーセントで返す

Posted on 5月 11, 2018 by Takaaki Naganoya

指定List中の指定要素が占める割合をパーセントの数値で返すAppleScriptです。

ローカルのiTunesライブラリに入っている楽曲のアーティスト名を集計して、各アーティストがiTunes Music Storeで販売している楽曲のうち、どの程度の割合でApple Musicでも配信しているかを調査するAppleScriptを作成するために作成したものです。

AppleScript名:指定のリスト中の指定要素が占める割合をパーセントで返す
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aList to {false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, true, true, true, false, true, true, true, true, true, true, true, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true}

set tPercent to calcOneItemsPercent(aList, true) of me
–> 62 (%)

–true/falseで構成されるlistのうち、指定要素が占める割合を%で計算。小数点以下を四捨五入
on calcOneItemsPercent(aList, targItem)
  set aLen to length of aList
  
set theCountedSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList
  
set tRes to (theCountedSet’s countForObject:targItem)
  
if tRes < 1 then return 0
  
set pRes to (tRes / aLen) * 100
  
return (round pRes rounding as taught in school)
end calcOneItemsPercent

★Click Here to Open This Script 

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

searchTreeKitを呼び出して1D List抽出

Posted on 5月 9, 2018 by Takaaki Naganoya

PJTernarySearchTreeをCocoa Framework化したsearchTreeKitを呼び出して、高速にテキスト検索を行う(はずの)AppleScriptです。

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

普通に1DのNSArrayにテキストを入れて絞り込みを行うよりもスピード面でメリットがあるのかは実測していないのでなんともいえません。PJTernarySearchTreeは検索フィールドの入力履歴からの候補語の検索などに利用するために作られた部品のようです。

AppleScript名:SearchTreeKitのじっけん1(ファイル書き込み)
— Created 2018-05-08 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "SearchTreeKit" –https://github.com/peakji/PJTernarySearchTree

set savePath to POSIX path of (path to desktop) & (do shell script "uuidgen") & "_test.tree"

set aTree to current application’s PJTernarySearchTree’s alloc()’s init()
aTree’s insertString:"http://www.peakji.com"
aTree’s insertString:"http://www.peak-labs.com"
aTree’s insertString:"http://www.facebook.com"
aTree’s insertString:"http://www.face.com"
aTree’s insertString:"http://blog.foo.com"
aTree’s insertString:"http://blog.foo.com/bar"

aTree’s insertString:"http://chinese.hello.com/ぴよー"
aTree’s insertString:"http://chinese.hello.com/ぴよぴよー"

aTree’s saveTreeToFile:savePath

★Click Here to Open This Script 

AppleScript名:SearchTreeKitのじっけん2(ファイル読み込み)
— Created 2018-05-08 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "SearchTreeKit" –https://github.com/peakji/PJTernarySearchTree

set savePath to POSIX path of (choose file)

set aTree to current application’s PJTernarySearchTree’s treeWithFile:savePath

set aRetrieved to (aTree’s retrievePrefix:"http://" countLimit:0) as list
–return aRetrieved
–>  {"http://blog.foo.com", "http://blog.foo.com/bar", "http://chinese.hello.com/ぴよぴよー", "http://chinese.hello.com/ぴよー", "http://www.face.com", "http://www.facebook.com", "http://www.peak-labs.com", "http://www.peakji.com"}

set bRetrieved to (aTree’s retrievePrefix:"http://" countLimit:2) as list
–return bRetrieved
–>{"http://blog.foo.com", "http://blog.foo.com/bar"}

set cRetrieved to (aTree’s retrievePrefix:"http://www." countLimit:0) as list
–return cRetrieved
–>  {"http://www.face.com", "http://www.facebook.com", "http://www.peak-labs.com", "http://www.peakji.com"}

–Remove a string or object
aTree’s removeString:"http://www.face.com"
set dRetrieved to (aTree’s retrievePrefix:"http://www.fa." countLimit:0) as list
–>  {}

★Click Here to Open This Script 

AppleScript名:SearchTreeKitのじっけん3(オブジェクトの追加と検索)
— Created 2018-05-09 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "SearchTreeKit" –https://github.com/peakji/PJTernarySearchTree

set tagSearchTree to current application’s PJTernarySearchTree’s alloc()’s init()
tagSearchTree’s insertString:"abcd"
(
tagSearchTree’s retrievePrefix:"abc") as list
–>  {​​​​​"abcd"​​​}

tagSearchTree’s insertString:"def"
tagSearchTree’s insertString:"ghi"

tagSearchTree’s removeString:"abcd"

set aList to (tagSearchTree’s retrievePrefix:"") as list
–>  {"def", ​​​​​"ghi"​​​}

★Click Here to Open This Script 

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

1D Listから指定文字列で終わっている要素を削除して返す

Posted on 4月 25, 2018 by Takaaki Naganoya

1D Listから指定文字列で終わっている要素を削除して返すAppleScriptです。

AppleScript名:1D Listから指定文字列で終わっている要素を削除して返す
— Created 2018-04-24 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aList to {"aVar", "level1’s", "level2’s", "level3’s", "bVar", "level10’s", "level11’s", "level12’s"}
set bList to my fiter1DList:(aList) byTailingKeyword:"’s"
–> {"aVar", "bVar"}

–指定文字列が末端にある要素を除外
on fiter1DList:(aList as list) byTailingKeyword:(keyWord as string)
  set itemCount1 to count every item of aList
  
set tmpArray to current application’s NSMutableArray’s arrayWithArray:aList
  
set thePred2 to current application’s NSPredicate’s predicateWithFormat_("!(self ENDSWITH %@)", keyWord)
  
set bArray to (tmpArray’s filteredArrayUsingPredicate:thePred2) as list of string or string
  
return bArray
end fiter1DList:byTailingKeyword:

★Click Here to Open This Script 

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

指定キーワードで始まるリスト要素をリストアップ

Posted on 4月 25, 2018 by Takaaki Naganoya

2D List(配列)のうち、最初の項目が指定キーワードではじまる要素をリストアップするAppleScriptです。

AppleScript名:指定キーワードで始まるリスト要素をリストアップ
— Created 2017-05-2 by Takaaki Naganoya
— 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aList to {{"A1 uploading", 2, 2}, {"A2 loginAndDownload", 1, 1}, {"A11 selfCheck", 3, 1}}

set bList to my fiter2DList:(aList) byHeadingKeyword:"A1"
–> {"A1 TEST1", 2, 2}

on fiter2DList:(pathList as list) byHeadingKeyword:(keyWord as string)
  set keyWord2 to keyWord & " " –ここが重要
  
set itemCount1 to count every item of pathList
  
set tmpArray to current application’s NSMutableArray’s arrayWithArray:pathList
  
  
–指定キーワードで始まるファイルをリストアップ
  
set thePred2 to current application’s NSPredicate’s predicateWithFormat_("self[0] BEGINSWITH %@", keyWord2)
  
set bArray to (tmpArray’s filteredArrayUsingPredicate:thePred2) as list of string or string
  
if bArray = {} then return false
  
return bArray
end fiter2DList:byHeadingKeyword:

★Click Here to Open This Script 

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

AS構文色分け情報の重複チェック

Posted on 4月 23, 2018 by Takaaki Naganoya

plistから読み取ったAppleScriptの構文色分け書式データをもとに、各構文要素の指定色に重複がないかどうかチェックするAppleScriptです。

もう少しシンプルに書けそうな気もするのですが、、、

AppleScript名:AS構文色分け情報の重複チェック
— Created 2018-04-22 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aList to {{redValue:145, greenValue:40, blueValue:144, fontName:"Osaka", fontSize:13.0}, {redValue:61, greenValue:12, blueValue:62, fontName:"Osaka", fontSize:13.0}, {redValue:14, greenValue:62, blueValue:251, fontName:"Osaka", fontSize:13.0}, {redValue:120, greenValue:52, blueValue:203, fontName:"Osaka", fontSize:13.0}, {redValue:255, greenValue:0, blueValue:0, fontName:"Osaka", fontSize:13.0}, {redValue:0, greenValue:0, blueValue:0, fontName:"Osaka", fontSize:13.0}, {redValue:145, greenValue:82, blueValue:17, fontName:"Osaka", fontSize:13.0}, {redValue:0, greenValue:0, blueValue:0, fontName:"Osaka", fontSize:13.0}, {redValue:39, greenValue:201, blueValue:201, fontName:"Osaka", fontSize:13.0}, {redValue:15, greenValue:62, blueValue:251, fontName:"Osaka", fontSize:13.0}, {redValue:31, greenValue:182, blueValue:252, fontName:"Osaka", fontSize:13.0}, {redValue:129, greenValue:58, blueValue:217, fontName:"Osaka", fontSize:13.0}, {redValue:93, greenValue:54, blueValue:146, fontName:"Osaka", fontSize:13.0}, {redValue:185, greenValue:12, blueValue:128, fontName:"Osaka", fontSize:13.0}, {redValue:25, greenValue:184, blueValue:126, fontName:"Osaka", fontSize:13.0}, {redValue:156, greenValue:145, blueValue:5, fontName:"Osaka", fontSize:13.0}, {redValue:79, greenValue:0, blueValue:136, fontName:"Osaka", fontSize:13.0}, {redValue:18, greenValue:138, blueValue:139, fontName:"Osaka", fontSize:13.0}}

set cRes to chkASLexicalFormatColorConfliction(aList) of me
–> false–重複があった

on chkASLexicalFormatColorConfliction(aList)
  set anArray to current application’s NSArray’s arrayWithArray:aList
  
set bList to (anArray’s valueForKeyPath:"redValue.stringValue") as list
  
set cList to (anArray’s valueForKeyPath:"greenValue.stringValue") as list
  
set dList to (anArray’s valueForKeyPath:"blueValue.stringValue") as list
  
  
set colStrList to {}
  
repeat with i from 1 to (length of bList)
    set bItem to contents of item i of bList
    
set cItem to contents of item i of cList
    
set dItem to contents of item i of dList
    
set the end of colStrList to bItem & " " & cItem & " " & dItem
  end repeat
  
  
set aRes to returnDuplicatesOnly(colStrList) of me
  
if aRes is equal to {} then
    return true –重複が存在しなかった場合
  else
    return false –重複があった場合
  end if
end chkASLexicalFormatColorConfliction

on returnDuplicatesOnly(aList as list)
  set aSet to current application’s 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 file list OSA Record | Tagged 10.11savvy 10.12savvy 10.13savvy | 1 Comment

2D Listをアイテム数でフィルタリングする

Posted on 4月 9, 2018 by Takaaki Naganoya
AppleScript名:2D Listをアイテム数でフィルタリングする
— Created 2018-04-09 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aList to {{"1"}, {"2", "2"}, {"3", "3", "3"}, {"4", "4", "4", "4"}, {"5", "5", "5", "5", "5"}, {"6", "6", "6", "6", "6", "6"}, {"7", "7", "7", "7", "7", "7", "7"}, {"8", "8", "8", "8", "8", "8", "8", "8"}}
set minItemNum to 7
set itemRes1 to retFilterItemMinNum(aList, minItemNum) of me
–> {{"7", "7", "7", "7", "7", "7", "7"}, {"8", "8", "8", "8", "8", "8", "8", "8"}}

set itemRes2 to retFilterItemEquNum(aList, minItemNum) of me
–> {{"7", "7", "7", "7", "7", "7", "7"}}

set itemRes3 to retFilterItemMaxNum(aList, minItemNum) of me
–> {{"1"}, {"2", "2"}, {"3", "3", "3"}, {"4", "4", "4", "4"}, {"5", "5", "5", "5", "5"}, {"6", "6", "6", "6", "6", "6"}, {"7", "7", "7", "7", "7", "7", "7"}}

on retFilterItemMinNum(aList, minItemNum)
  set anArray to current application’s NSMutableArray’s arrayWithArray:aList
  
set predStr to "SELF[SIZE] >= " & (minItemNum as string)
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat:predStr
  
set t2Array to (anArray’s filteredArrayUsingPredicate:aPredicate) as list
  
return t2Array
end retFilterItemMinNum

on retFilterItemEquNum(aList, minItemNum)
  set anArray to current application’s NSMutableArray’s arrayWithArray:aList
  
set predStr to "SELF[SIZE] = " & (minItemNum as string)
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat:predStr
  
set t2Array to (anArray’s filteredArrayUsingPredicate:aPredicate) as list
  
return t2Array
end retFilterItemEquNum

on retFilterItemMaxNum(aList, minItemNum)
  set anArray to current application’s NSMutableArray’s arrayWithArray:aList
  
set predStr to "SELF[SIZE] <= " & (minItemNum as string)
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat:predStr
  
set t2Array to (anArray’s filteredArrayUsingPredicate:aPredicate) as list
  
return t2Array
end retFilterItemMaxNum

★Click Here to Open This Script 

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

配列に添字的なデータを指定してアクセス

Posted on 2月 27, 2018 by Takaaki Naganoya

AppleScriptのリスト(list)型変数に対して、一般的な配列の添字的なパラメータを指定して値の設定や取得を行うAppleScriptです。

一般的なプログラミング言語には必ず存在する配列変数、AppleScriptにも当然存在しており、リスト型(list)変数と呼ばれています。

一般的な配列変数と異なる点は3点ほど。

 ・配列要素が1からはじまる(item 0はない)
 ・配列要素への間接アクセスは可能なものの、item x of aListのように一般的な配列添字とは異なる記述を行う
 ・配列要素として各種GUIアプリケーションのオブジェクトやScriptオブジェクトを突っ込める

といったところでしょうか。あとは、条件抽出とかソートなどの機能は備わっていないので、昨今ではCocoaの機能を呼び出してNSArrayに変換してからこのような処理を行なっています(要素数が少ない(1万以下)場合には、AppleScriptだけでループ処理で条件抽出したほうが速い)。

ないものをない、と嘆くだけならアホでもできるので、配列添字的なアクセスがしたいのなら作ってしまえばいいじゃないか、ということで作ったのがこれです。

「Safariで現在見えている表を抽出してCSV書き出しv3」などの処理に使っています。多分、この処理は本ルーチンが存在していたからできたものです。

AppleScript名:配列に添字的なデータを指定してアクセス
— Created 2017-09-30 by Takaaki Naganoya
— 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aList to make2DBlankArray(3, 4) of me
set aList to setItemByXY(2, 3, aList, "@") of me
set aRes to getItemByXY(2, 3, aList, "") of me

return aList
–> {{"", "", ""}, {"", "", ""}, {"", "@", ""}, {"", "", ""}}

on getItemByXY(aX, aY, aList, aBlankItem)
  try
    set aContents to contents of (item aX of item aY of aList)
  on error
    set aContents to aBlankItem
  end try
  
return aContents
end getItemByXY

on setItemByXY(aX, aY, aList, aContents)
  set (item aX of item aY of aList) to aContents
  
return aList
end setItemByXY

–空白の2D Array を出力する
on make2DBlankArray(curLen, curMax)
  set outArray to {}
  
repeat curMax times
    set aList to {}
    
repeat curLen times
      set the end of aList to ""
    end repeat
    
set the end of outArray to aList
  end repeat
  
return outArray
end make2DBlankArray

★Click Here to Open This Script 

Posted in list | Tagged 10.11savvy 10.12savvy 10.13savvy | 1 Comment

配列の複数の要素を取得する

Posted on 2月 27, 2018 by Takaaki Naganoya

配列変数の要素を範囲指定して取得するAppleScriptです。

AppleScriptネイティブの配列変数であるリスト型変数であれば、

set aList to {1,2,3,4,5}
set bList to item 3 thru -1 of aList
--> {3, 4, 5}

のように1はじまりのインデックスを範囲指定して取得することになります。ここで紹介するのはCocoaのオブジェクトであるNSArrayから(0はじまりのインデックスで)範囲指定して要素を取り出す書き方です。

AppleScript名:配列の複数の要素を取得する
— Created 2015-09-02 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set anArray to current application’s NSArray’s arrayWithArray:{1, 2, 3}
–>  (NSArray) {​​​​​1, ​​​​​2, ​​​​​3​​​}

–複数の要素を取得する
set anInd to current application’s NSIndexSet’s indexSetWithIndexesInRange:(current application’s NSMakeRange(1, 2))
–>  (NSIndexSet) <NSIndexSet: 0x600000431140>[number of indexes: 2 (in 1 ranges), indexes: (1-2)]

set aRes to (anArray’s objectsAtIndexes:anInd) as list of string or string
–>  {​​​​​2, ​​​​​3​​​}

★Click Here to Open This Script 

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

配列の要素を順番に取得する

Posted on 2月 27, 2018 by Takaaki Naganoya

Cocoaの機能を用いて配列(NSArray)の要素を順番に取得するAppleScriptです。

Objective-CなどではEnumeratorを用いると配列からの順次要素取り出しの速度が上がるようですが、AppleScriptではEnumeratorを用いてもループ速度が上がったりしません。AppleScriptの普通のループを行ったほうが高速です。

どうしてもEnumeratorを使わなくてはならない場面にだけ、仕方なく使う感じでしょうか。

AppleScript名:配列の要素を順番に取得する
— Created 2015-09-02 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set anArray to current application’s NSArray’s arrayWithArray:{1, 2, 3}
–>  (NSArray) {​​​​​1, ​​​​​2, ​​​​​3​​​}

–要素を順番に取得する
set anEnum to anArray’s objectEnumerator()
–>  (__NSFastEnumerationEnumerator) <__NSFastEnumerationEnumerator: 0x6000002c1180>
repeat
  set aValue to anEnum’s nextObject()
  
if aValue = missing value then exit repeat
  
log aValue as list of string or string
end repeat

★Click Here to Open This Script 

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

Post navigation

  • Older posts
  • Newer posts

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

Google Search

Popular posts

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

Tags

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

カテゴリー

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

アーカイブ

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

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

メタ情報

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

Forum Posts

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

メタ情報

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