Archive for 3月, 2015

2015/03/31 POSIX pathで与えられたパスの親フォルダを求める(末尾にスラッシュ添付)

This ASOC script gets a parent folder from POSIX path string. And this script appends “/” character to the end of the POSIX path.

本ASOCのscriptはPOSIX path形式のパスから親フォルダを求めるものです。パスの末尾には”/”を付加します。

AppleScript名:POSIX pathで与えられたパスの親フォルダを求める(末尾にスラッシュ添付)
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set a to choose folder
set b to POSIX path of a
set c to getParentFromPOSIXpath(b)

–POSIX pathで与えられたパスの親フォルダを求める(末尾にスラッシュ添付)
on getParentFromPOSIXpath(b)
  set aStr to current application’s NSString’s stringWithString:b
  
set eStr to (aStr’s stringByDeletingLastPathComponent()) as string
  
return (eStr & "/")
end getParentFromPOSIXpath

★Click Here to Open This Script 

2015/03/29 ASOCで数値文字の比較

Shane wrote me a numeric strings comparison script. It can handle version numeric strings (ex. “10.10.3″).

Shaneによるバージョン番号を表記する数値文字列(10.10.3とか)の比較(equalのみ)を行うASOCのscriptです。イコールといっても、「10.10.0」と「10.10」が同一視されたりはしないので、これについては大小判定に意味があって、イコールについては少々実用性に疑問があります。ためしに、漢数字の数値文字列(例:二千十五)を与えてみましたが、そういうのはダメです。

AppleScript名:数値文字の比較
– Created 2015-03-28 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aRes to compareNumerically(1234, "1234")
–> true

set aRes to compareNumerically("1234", "1234.0")
–> false

set aRes to compareNumerically("1.23.4", "1.23.4.0")
–> false

–Numerical Strings Compare
on compareNumerically(aText as text, bText as text)
  set aStr to current application’s NSString’s stringWithString:aText
  
return (aStr’s compare:bText options:(current application’s NSNumericSearch)) = current application’s NSOrderedSame
end compareNumerically

★Click Here to Open This Script 

2015/03/29 Umlautを無視した文字列比較

Shane wrote me string comparison script considering Umlaut. Japanese language does not have effect about this.

Shaneが書いてくれた文字列比較のサンプルのうちのひとつで、ウムラウトの有無を無視するものです。ただし、日本語ではウムラウト記号は使わないので、影響がありません。

AppleScript名:Umlautを無視した文字列比較(NSDiacriticInsensitiveSearch)
– Created 2015-03-28 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aRes to compareIgnoringDiacriticals("AbC", "ÂbC")
–> true

set aRes to compareIgnoringDiacriticals("Abc", "Ábc")
–> true

set aRes to compareIgnoringDiacriticals("abc", "åbc")
–> true

–Strings Compare with ignoring Umlaut
on compareIgnoringDiacriticals(aText as text, bText as text)
  set aStr to current application’s NSString’s stringWithString:aText
  
return (aStr’s compare:bText options:((current application’s NSCaseInsensitiveSearch) + (current application’s NSDiacriticInsensitiveSearch as integer))) = current application’s NSOrderedSame
end compareIgnoringDiacriticals

★Click Here to Open This Script 

2015/03/29 文字列同士が同じかチェック(大文字,小文字の差異を考慮したり無視したり)

This script is a basic string comparison with considering case from Shane Stanley (and I rewrote a little).

Default pure AppleScript string comparison is “case insensitive”. Shane wrote case sensitive and insensitive string comparison ASOC scripts. So, I jointed them.

Shaneが英字大文字/小文字を考慮したASOCのscirptを書いてくれました。それらを若干書き直したものです。

純粋な(Cocoaの機能を用いない)AppleScriptの文字列比較では、英字大文字/小文字の違いを無視する(case insensitive)ようになっています。Shaneはその両方のASOCバージョンのscriptを書いたのですが、それらを一つにまとめてみました。

AppleScript名:文字列同士が同じかチェック(大文字,小文字の差異を考慮したり無視したり)
– Created 2015-03-28 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aRes to aIsEqualtoB("リットル", "", false)
–> false

set aRes to aIsEqualtoB("リットル", "", true)
–> false

set aRes to aIsEqualtoB("あいうえお", "アイウエオ", false)
–> false

set aRes to aIsEqualtoB("あいうえお", "ぁぃぅぇぉ", true)
–> false

set aRes to aIsEqualtoB("ABCD", "abcd", false)
–> true

set aRes to aIsEqualtoB("ABCD", "abcd", true)
–> false

–Strings Comparison in ASOC
on aIsEqualtoB(aText as text, bText as text, caseSensitive as boolean)
  set aStr to current application’s NSString’s stringWithString:aText
  
if caseSensitive = false then
    return (aStr’s caseInsensitiveCompare:bText) = current application’s NSOrderedSame –Case Insensitive
  else
    return (aStr’s compare:bText) = current application’s NSOrderedSame –Case Sensitive
  end if
end aIsEqualtoB

★Click Here to Open This Script 

2015/03/29 ASOCで基礎的な文字列比較 2

Shane Stanley wrote me shorter version of string comparison methods in AppleScriptObjC(ASOC).

ASOCの基礎的な文字列比較について、Shane Stanleyから「もっと短くかけるよ」と教えてもらいました。

AppleScript名:文字列同士が同じかチェック v2
– Created 2015-03-28 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aRes to aIsEqualtoB("リットル", "")
–> false

set aRes to aIsEqualtoB("あいうえお", "アイウエオ")
–> false

set aRes to aIsEqualtoB("あいうえお", "あいうえお")
–> true

on aIsEqualtoB(aText as text, bText as text)
  set aStr to current application’s NSString’s stringWithString:aText
  
return (aStr’s isEqualToString:bText) as boolean
end aIsEqualtoB

★Click Here to Open This Script 

AppleScript名:指定文字で始まるかチェック v2
– Created 2015-03-28 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aRes to aBeginsWithB("gggggabcdefg", "a")
–> false

set aRes to aBeginsWithB("gggggabcdefg", "g")
–> true

on aBeginsWithB(aText as text, bText as text)
  set aStr to current application’s NSString’s stringWithString:aText
  
return (aStr’s hasPrefix:bText) as boolean
end aBeginsWithB

★Click Here to Open This Script 

AppleScript名:指定文字で終わるチェック v2
– Created 2015-03-28 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aRes to aEndsWithB("gggggabcdefg", "a")
–> false

set aRes to aEndsWithB("gggggabcdefg", "g")
–> true

on aEndsWithB(aText as text, bText as text)
  set aStr to current application’s NSString’s stringWithString:aText
  
return (aStr’s hasSuffix:bText) as boolean
end aEndsWithB

★Click Here to Open This Script 

2015/03/28 ASOCで基礎的な文字列比較

Basic strings comparison methods in AppleScriptObjC (ASOC). To fix ASOC script as ASOC in Xcode (Cocoa Script Application).

ASOCの基礎的な文字列比較方法についてまとめておきました。ASOCのScriptをXcode上のASOC用に書き換える際に必要になった場合に備えて用意しておきました。

AppleScript名:文字列同士が同じかチェック
– Created 2015-03-26 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aRes to aIsEqualtoB("リットル", "")
–> false

set aRes to aIsEqualtoB("あいうえお", "アイウエオ")
–> false

set aRes to aIsEqualtoB("あいうえお", "あいうえお")
–> true

on aIsEqualtoB(aText as text, bText as text)
  set aStr to current application’s NSString’s stringWithString:aText
  
set bStr to current application’s NSString’s stringWithString:bText
  
return (aStr’s isEqualToString:bStr) as boolean
end aIsEqualtoB

★Click Here to Open This Script 

AppleScript名:指定文字で始まるかチェック
– Created 2015-03-26 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aRes to aBeginsWithB("gggggabcdefg", "a")
–> false

set aRes to aBeginsWithB("gggggabcdefg", "g")
–> true

on aBeginsWithB(aText as text, bText as text)
  set aStr to current application’s NSString’s stringWithString:aText
  
set bStr to current application’s NSString’s stringWithString:bText
  
set aRes to aStr’s rangeOfString:bStr options:(current application’s NSAnchoredSearch)
  
set bRes to aRes’s |length| as integer
  
return (bRes = 1)
end aBeginsWithB

★Click Here to Open This Script 

AppleScript名:指定文字を含むかチェック
– Created 2015-03-26 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aRes to aContainsB("abcdefg", "z")
–> false

set aRes to aContainsB("abcdefg", "d")
–> true

on aContainsB(aText as string, bText as string)
  set aStr to current application’s NSString’s stringWithString:aText
  
set bStr to current application’s NSString’s stringWithString:bText
  
set aRes to aStr’s rangeOfString:bStr
  
set bRes to aRes’s |length| as integer
  
return (bRes > 0)
end aContainsB

★Click Here to Open This Script 

2015/03/25 公開添削:サーバー上のファイル権限をローカルで書き換えて書き戻し

This is a special correction of my friend’s AppleScript. He is a beginner of AppleScript. So, I confused by his script and struggled with it.

At first, I didn’t understand original script at all. After several mail transactions, I understood his thought.

step1: Re-confirm the specification. Your spec is only in your brain. I don’t understand at all
step2: Where is comments?
step3: Make blank line to separate processing blocks
step4: Don’t make droplet. It is hard to debug!!
step5: The name of variables are important
step6: Mis-matching sub-routine’s spec
step7: Change the name of sub-routine


知り合いが「AppleScriptのバグが抜けない」と言っていたので、バーターで(未公開ソフトの評価)バグ抜き&公開指導をしてみることにしました。

「サーバ管理権限のないマシンから得意先が投げてきたアクセス権のおかしいファイルをフォルダごとローカルにコピーしてアクセス権を変更して元の階層に上書き、という内容のもと、ASを手習い中であります。

(Finderの)「内包している項目に適用」に相当する命令が見つからずループ仕立てにしてみています。まだまだAS自体つかめておらず、ほとんど拾ったコードのつぎはぎですが。」

▼Danger!!! Never Execute This Script.

AppleScript名:Original Script
【コメント】 Don’t Execute!!! This Script is incomplete!!!
————-
on open fileList
  tell application “Finder”
    set myDir to (parent of item 1 of fileList)
    
set aList to duplicate fileList to desktop
    
repeat with aItem in aList
      DiveFolder(aItem) of me
    end repeat
    
–move aList to myDir
    
–[true]
    
–delete aList
  end tell
end open

on DiveFolder(thePath)
  tell application “Finder”
    set theFiles to every file of thePath
    
repeat with aFile in theFiles
      set owner privileges of aFile to read write
      
set everyones privileges of aFile to read only
    end repeat
    
set theFolders to every folder of thePath
    
repeat with aFolder in theFolders
      DiveFolder(aFolder) of me
    end repeat
  end tell
end DiveFolder
————-

★Click Here to Open This Script 

チェック項目1:仕様がよくわからない

最初、すでにローカルにコピーしておいたものをScriptで処理するのかと思っていたのですが、違うとのこと。何度かメールをやりとりして、ようやく理解しました。

チェック項目2:コメントがない

自分の書いたScriptでも1日もたつと内容を忘れてしまいがちです。他人が書いたものだと、暗号解読に近いものになります。

コメントがないと、どういう意図のもとに書かれたのかが分からず、とても読みにくいです。

どういう意図で処理をしているのか、適度にコメントを入れましょう(サンプルでは、かなり多めに=過剰に入れています)。

チェック項目3:空行がなくて読みにくい

個人の趣味の問題ではありますが、処理上のまとまりが途切れたところで空行を入れると読みやすくなり、処理の意図が通じやすくなります。書き換え前後の比較を行うと一目瞭然です。

チェック項目4:Dropletをいきなり作るのはダメ

初心者にありがちな「実力不相応な高い到達点にいきなり行こうとする」パターンです。

Script Editorにはデバッグのための簡単な機能(ログ表示機能)がありますが、Dropletはアプリケーション形式でしか機能せず、アプリケーション形式で動かすとログを表示させたり動作内容を確認することができません。最後の最後でドロップレットにするとしても、最初はもっと低い到達点から、確実に動作することを確認しながら書き始めるべきです。

最初は、choose file/choose folderで選択するのがベスト。もうちょっとスマートにしたいなら、Finderのselectionを取得。Dropletにするのは、すべてが完成したあとの話です。

それでも、最初からDropletを作りたい場合にはScript Debuggerを買いましょう。Dropletもデバッグできます。初心者にこそ、Script Debuggerは有益です(そこらへんで、ニーズを持っているユーザー層とScript Debuggerの価格がマッチしていない)。

チェック項目5:変数名がさっぱりわからない

作者の意図が変数名からはさっぱり読み取れませんでした。小さなサブルーチン内でa、b、c、i、jといった変数名を使うこともありますが、極力、意図を反映したものにすべきでしょう。

チェック項目6:サブルーチンの仕様と呼び出す側の処理が合っていない

サブルーチン「DiveFolder」は、フォルダを渡すと再帰でその中身を探索しつつ、ファイルに対して所有者には読み書き可能な権限を、他のユーザーには読み出し可能な権限を与えるようになっています。

最初のプログラムでは、わざわざファイルを個別に渡すようになっており、サブルーチンを書いた人の意図を無視しています(サブルーチン側にもコメントがないことが問題。コメントを書かないのは本当に罪悪)。

チェック項目7:サブルーチン名が意味不明

だいたい、「DiveFolder」って、その中二病感満載の名前はなんじゃそりゃ(汗) 再帰でフォルダ内容の権限を書き換えるよ、という意図がわかる名前にしてほしいところです。あと、暗黙のルールでAppleScriptのハンドラ名(サブルーチン名)はCamel Caseで書くのがふつうです(DiveFolder→diveFolder)。

何度かやりとりをして、Keynote上で仕様を確認してみたりして、ようやく書き換えたのがこれ(↓)です。

AppleScript名:サーバー上の指定フォルダ内の全アクセス権限をローカルで書き換えて書き戻す
–  サーバー上にある特定フォルダ内のすべてのファイルを、ローカルにコピー(デスクトップ)し、
–  アクセス権限を変更して、サーバー上の元フォルダを消去して、ローカルのフォルダをアップロードする

set remoteFol to choose folder with prompt “サーバー上の、権限書き換え対象のフォルダを選択”

tell application “Finder”
  –権限を書き換えたフォルダを、あとでサーバーに書き戻すために準備
  
set returnFol to parent of remoteFol –最初に指定したフォルダの親フォルダを求めておく
  
  
–サーバー上のファイルをローカルのデスクトップ上にコピー
  
with timeout of 3600 seconds –遅いネットワーク(無線LANなど)を考慮(デフォルトでは180秒でタイムアウトでエラーに)
    set aLocalFol to (duplicate remoteFol to desktop with replacing) –同名のフォルダがあったら上書き
  end timeout
  
  
–ローカルのファイルをすべて権限書き換え
  
chmodRecursive(aLocalFol) of me
  
  
–サーバー上のフォルダを削除
  
delete remoteFol –shell scriptで”rm -rf”したくなる、、
  
empty trash
  
  
–サーバーにアップロード
  
with timeout of 3600 seconds –遅いネットワーク(無線LANなど)を考慮(デフォルトでは180秒でタイムアウトでエラーに)
    duplicate aLocalFol to returnFol
  end timeout
  
  
–あとしまつ。デスクトップ上にコピーしてきたフォルダを抹消
  
delete aLocalFol
  
empty trash
  
end tell

–指定フォルダ以下のすべてのファイルの権限を書き換える
on chmodRecursive(thePath) –サブルーチン名がぜんぜん意味不明だったのでリネーム
  tell application “Finder”
    
    
–ファイルに対しての処理を行う
    
set theFiles to every file of thePath
    
repeat with aFile in theFiles
      set owner privileges of aFile to read write
      
set everyones privileges of aFile to read only
    end repeat
    
    
–フォルダに対しての処理を再帰呼び出しで行う
    
set theFolders to every folder of thePath
    
repeat with aFolder in theFolders
      chmodRecursive(aFolder) of me –ここで再帰
    end repeat
    
  end tell
end chmodRecursive

★Click Here to Open This Script 

2015/03/23 連番の追加によるファイル名の重複回避

This is a typical file name collision checking & generating child number process AppleScriptObjC script. The child number’s max is 65535.

Pure AppleScript version is here.

ファイル名の重複チェックと、重複時の回避のために子番号(1〜65535)を付加するAppleScriptObjCのScriptです。

純粋なAppleScriptだけで書いた(Cocoaの機能を利用していない)ものがこちらです(完全に同じ機能ではないものの、同様の機能を実現)。

AppleScript名:連番の追加によるファイル名の重複回避
– Created 2015-03-23 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aa to “/Users/me/Desktop/P0000_000.csv”

set ab to chkExistAndIncrementChildNumber(aa)
–>  ”/Users/me/Desktop/P0000_000_1.csv” –Case: there is file name conflict
–>  ”/Users/me/Desktop/P0000_000.csv”–Case: there is No file name conflict

on chkExistAndIncrementChildNumber(aa)
  set aStr to current application’s NSString’s stringWithString:aa
  
  
–ファイルパス(フルパス)からファイル名部分を取得
  
set bStr to aStr’s lastPathComponent()
  
–> “P0000_000.csv”
  
  
–ファイル名から拡張子を取得
  
set cStr to (bStr’s pathExtension()) as string
  
–> “csv”
  
  
–ファイル名から拡張子を削除
  
set dStr to (bStr’s stringByDeletingPathExtension()) as string
  
–> “P0000_000″
  
  
–ファイルパス(フルパス)から親フォルダを取得(ただし末尾はスラッシュになっていない)
  
set eStr to (aStr’s stringByDeletingLastPathComponent()) as string
  
–>  ”/Users/me/Desktop”
  
  
set aManager to current application’s NSFileManager’s defaultManager()
  
set aRes to (aManager’s fileExistsAtPath:aStr) as boolean
  
if aRes = false then return aa
  
  
set hitF to false
  
repeat with i from 1 to 65535
    
    
set tmpPath to (eStr & “/” & dStr & “_” & (i as string) & “.” & cStr)
    
set tmpStr to (current application’s NSString’s stringWithString:tmpPath)
    
set aRes to (aManager’s fileExistsAtPath:tmpStr) as boolean
    
set bRes to ((tmpStr’s caseInsensitiveCompare:eStr) is not equal to (current application’s NSOrderedSame)) as boolean
    
    
if {aRes, bRes} = {false, true} then
      set hitF to true
      
exit repeat
    end if
    
  end repeat
  
  
if hitF = false then return false
  
  
return tmpStr as string
  
end chkExistAndIncrementChildNumber

★Click Here to Open This Script 

2015/03/23 複数行コメントにpipe文字「|」が入らない

Most famous topic in AppleScript Users ML in this week is “|” in comment.

AppleScript has three type of comment. Single line comment begins with “–” (traditional) and “#”(newer). Multiple line comment begins with “(*” and ends with “*)”.

This multiple line comment can not contain “|”. It is a surprise. Nobody noticed it. I checked OS X 10.6.8, 10.7.5 and 10.10.2. All environment could not compile.

ed0.png

I check this on Mac OS 8.6 on Sheep Shaver (Classic Mac OS emulator) and found same result.

img_2864.JPG

ed1.jpg

ed2.jpg

ed3.jpg

——

先週AppleScript Users MLで一番の盛り上がりを見せた内容はコメント中の「|」(pipe)についてです。

AppleScriptには3タイプのコメントが使えます。1行コメントには、伝統的な「–」で始まるものと、最近できた「#」で始まるものがあります。もうひとつが複数行コメントで、「(*」ではじまり、「*)」で終わります。

この複数行コメント内に「|」(pipe)文字が入れられない。誰も気づかなかったのか。OS X 10.6.8、10.7.5、10.10.2で確認しましたが、すべての環境でScript Editor上でコンパイル(構文確認)できませんでした。

念のために、Classic Mac OSエミュレーター上でMac OS 8.6を動かして確認してみたところ、同様にエラーになりました。

AppleScript名:複数行コメントにpipe文字が入らない
(*
this is a comment test — without pipe
*)

(*
this is a comment | test
*)

# this is a comment | test —compile OK

– this is a comment | test–compile OK

★Click Here to Open This Script 

2015/03/21 同スコアを考慮した順位決定

This AppleScript decide ranking considering same score case. In normal case, ranking increases one by one. If same score continues, the rank remain same.

When I make auto MS sortie ranking AppleScript from “Senjo-No-Kizuna” personal page, I made it very simple one. So the ranking did not consider the same score case.

This AppleScript consider the “same score case”.

score1.png

score2.png

score3.png

このAppleScriptは、ランキングの順位決定において「同じスコア」が発生した場合を考慮したものです。通常、順位は1→2→3と1きざみでカウントアップします。もし、同じスコアが続いた場合には、順位は据え置きとなります。

「戦場の絆」のマイページの情報を読み取って、出撃MSの回数ランキングを自動生成するAppleScriptを作成した際に、単純なランキング決定を行っていました。そのため、「同じスコア」を考慮していませんでした。

本AppleScriptでは、きちんと同じスコアを考慮しています。

AppleScript名:同スコアを考慮した順位決定
use AppleScript version “2.4″
use scripting additions

set rList to {{“近 装甲強化型ジム COST: 200″, 60}, {“遠 ジム・キャノン COST: 160″, 39}, {“近 ジム・コマンド COST: 200″, 32}, {“近 ジム(WD隊) COST: 160″, 26}, {“近 陸戦型ガンダム COST: 220″, 23}, {“近 ジム改 COST: 240″, 22}, {“遠 ガンタンク COST: 200″, 21}, {“格 ジム(指揮官機) COST: 160″, 20}, {“近 ジム COST: 120″, 19}, {“格 陸戦型ジム COST: 120″, 10}, {“近 ジム・トレーナー COST: 120″, 9}, {“射 ジム・スナイパーII(WD隊) COST: 220″, 8}, {“射 陸戦型ガンダム(ジム頭) COST: 200″, 7}, {“格 ガンダム COST: 280″, 6}, {“近 ザクII(F2) COST: 160″, 6}, {“格 ジム・ストライカー COST: 180″, 4}, {“近 ジム・寒冷地仕様 COST: 200″, 4}, {“狙 ジム・スナイパーカスタム COST: 200″, 3}, {“近 アクア・ジム COST: 160″, 2}, {“遠 量産型ガンタンク COST: 160″, 2}, {“格 ガンキャノン重装型 COST: 160″, 1}, {“近 ジム・コマンドライトアーマー COST: 160″, 1}, {“射 ガンキャノン COST: 200″, 1}, {“格 ボールK型 COST: 120″, 0}, {“射 デザート・ジム COST: 160″, 0}}

–テキスト整形出力(human readbleな形式に変換)
set aText to “”
set aCount to 0

set prevPoint to -1
set buffCount to 0

repeat with i in rList
  
  
copy i to {j, bCount}
  
  
if prevPoint = bCount then
    –同じポイントが続いた場合
    
if buffCount is not equal to 0 then
      –同じポイントが複数回(2回以上)続いている場合
      
set buffCount to buffCount + 1
      
log {“case A:”, buffCount, aCount, bCount, prevPoint}
    else
      –同じポイントが続いている場合(2回目)
      
set buffCount to 1
      
log {“case B:”, buffCount, aCount, bCount, prevPoint}
    end if
  else
    –同じポイントが続いていない場合
    
if buffCount is not equal to 0 then
      –直前まで同じポイントが続いていた場合
      
set aCount to aCount + buffCount + 1 –バッファしておいたカウントを出力する
      
set buffCount to 0
      
log {“case C:”, buffCount, aCount, bCount, prevPoint}
    else
      –通常パターン(直前まで同じポイントが続いていたりしない)
      
set buffCount to 0
      
set aCount to aCount + 1 –ランキング順位を+1
      
log {“case D:”, buffCount, aCount, bCount, prevPoint}
    end if
  end if
  
  
set aTmp to retArrowText(i, “ = ”) of me –搭乗回数を全角イコールと全角スペースではさんで連結
  
set aText to aText & “■” & ((aCount as string) & “位 ”) & aTmp & “回” & return –整形
  
  
copy bCount to prevPoint
  
end repeat

return aText
–>
(*
“■1位 近 装甲強化型ジム COST: 200 = 60回
■2位 遠 ジム・キャノン COST: 160 = 39回
■3位 近 ジム・コマンド COST: 200 = 32回
■4位 近 ジム(WD隊) COST: 160 = 26回
■5位 近 陸戦型ガンダム COST: 220 = 23回
■6位 近 ジム改 COST: 240 = 22回
■7位 遠 ガンタンク COST: 200 = 21回
■8位 格 ジム(指揮官機) COST: 160 = 20回
■9位 近 ジム COST: 120 = 19回
■10位 格 陸戦型ジム COST: 120 = 10回
■11位 近 ジム・トレーナー COST: 120 = 9回
■12位 射 ジム・スナイパーII(WD隊) COST: 220 = 8回
■13位 射 陸戦型ガンダム(ジム頭) COST: 200 = 7回
■14位 格 ガンダム COST: 280 = 6回
■14位 近 ザクII(F2) COST: 160 = 6回
■16位 格 ジム・ストライカー COST: 180 = 4回
■16位 近 ジム・寒冷地仕様 COST: 200 = 4回
■18位 狙 ジム・スナイパーカスタム COST: 200 = 3回
■19位 近 アクア・ジム COST: 160 = 2回
■19位 遠 量産型ガンタンク COST: 160 = 2回
■21位 格 ガンキャノン重装型 COST: 160 = 1回
■21位 近 ジム・コマンドライトアーマー COST: 160 = 1回
■21位 射 ガンキャノン COST: 200 = 1回
■24位 格 ボールK型 COST: 120 = 0回
■24位 射 デザート・ジム COST: 160 = 0回

*)

–リストを任意のデリミタ付きでテキストに
on retArrowText(aList, aDelim)
  set aText to “”
  
set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to aDelim
  
set aText to aList as text
  
set AppleScript’s text item delimiters to curDelim
  
return aText
end retArrowText

★Click Here to Open This Script 

2015/03/18 レコードとレコードの連結

This AppleScript is a sample of concatenation of multiple records. If two records have same property-labeled element & different value….

複数のレコードの連結を行うAppleScriptサンプルです。ラベル値が同じものは1つにまとめられる、というのはわかりますが、異なる値を持つ場合の挙動には注意が必要です。

AppleScript名:レコードとレコードの連結
–Case: same label (fullName) and same value ("abc")
set aRec to {fullName:"abc", anAge:46}
set bRec to {fullName:"abc", aInfo:10}

set cRec to aRec & bRec
–> {fullName:"abc", anAge:46, aInfo:10}

–Case: same label (fullName) and different value ("abc", "def")
set dRec to {fullName:"abc", anAge:46}
set eRec to {fullName:"def", aInfo:10}

set fRec to dRec & eRec
–> {fullName:"abc", anAge:46, aInfo:10}

set gRec to eRec & dRec
–> {fullName:"def", aInfo:10, anAge:46}

★Click Here to Open This Script 

2015/03/16 errorのpartial resultとは?

“error” is a hot topic in AppleScript Users ML which is hosted by US Apple.

“partial result” is a result parameter of “try…on error…end try” clause but I didn’t acknowledge about this.

—–

US Appleがホスティングしている「AppleScript Users ML」でここのところの熱い話題といえば「error」について。

“try…on error…end try”節のパラメータに「partial result」なるものがあるのですが、見たことがありませんでした(汗) 知っていてもプラスにならず、知らなくてもダメージがない枝葉な仕様。

AppleScript名:errorのpartial resultとは?
–By Ed Stockly
–2015/3/14

try
  MyFirstHandler()
on error errMsg number ErrNbr partial result partialResult from from_ to to_
  log errMsg
  
–> (*”ccc” のタイプを number に変換できません。*)
  
log ErrNbr
  
–> (*-2700*)
  
log partialResult
  
–> (**)
  
log from_
  
–> (*MyFirstHandler*)
  
log to_
  
–> (*item*)
end try

on MyFirstHandler()
  set handlerName to “MyFirstHandler”
  
try
    set bb to 3 * “ccc”
  on error errMsg number ErrNbr partial result partialResult from from_ to to_
    log errMsg
    
–> (*”ccc” のタイプを number に変換できません。*)
    
log ErrNbr
    
–> (*-1700*)
    
log partialResult
    
–> (**)
    
log from_
    
–> (*ccc*)
    
log to_
    
–> (*number*)
    
error errMsg from handlerName
  end try
end MyFirstHandler

★Click Here to Open This Script 

2015/03/12 CSVファイルをListにParseする(ASOC) 2

Shane Stanley rewrote me a true contents of his ASObjCExtras.framework’s “arrayFromCSV: commaIs:” method. Original version is written in Objective-C. He translated it into AppleScriptObjC to be understood for scripters.

There was no comment in his ASOC program and no blank line. So, I added comments and blanks to make it easy to read.

The script is very appropriate and tidy. To parse CSV file considering double-quote escape and irregular comma, there is need to use some flags to detect the state. The script have to scan CSV file by a character.

—-Japanese

ShaneがASObjCExtras.frameworkを用いてシンプルに書いたCSV parser scriptの「中身」(arrayFromCSV: commanIs:メソッド)をObjective-CからAppleScriptObjCに書き直して送ってくれました(理解しやすいように)。

ShaneのScriptにはコメントも空行も何もなかったので、解析ついでにいろいろコメントを足したり読みやすいように空行を追加しました。

Scriptの内容はきわめてまっとうで丁寧です。CSVをparseするには、ダブルクォート文字とかイレギュラーに行末に入るカンマがあったりとか、そうしたものを処理するためにいくつかのフラグを用いて根気よく処理する必要があります。ScriptはCSVを先頭から1文字づつ調べていく必要があります(もうちょっとは楽をしているかも)。

AppleScript名:CSVのParse 5(ASOC)
–Created By Shane Stanley 2015/03/12
–Commented & Arranged By Takaaki Naganoya 2015/03/12

use scripting additions
use framework “Foundation”

set theString to “cust1,\”prod,1\”,season 1,
cust1,prod1,season2,
cust2,prod1,event1,season1
cust2,prod3,event1,season 1″

its makeListsFromCSV:theString commaIs:“,”
–>  {​​​​​{​​​​​​​”cust1″, ​​​​​​​”prod,1″, ​​​​​​​”season 1″​​​​​}, ​​​​​{​​​​​​​”cust1″, ​​​​​​​”prod1″, ​​​​​​​”season2″​​​​​}, ​​​​​{​​​​​​​”cust2″, ​​​​​​​”prod1″, ​​​​​​​”event1″, ​​​​​​​”season1″​​​​​}, ​​​​​{​​​​​​​”cust2″, ​​​​​​​”prod3″, ​​​​​​​”event1″, ​​​​​​​”season 1″​​​​​}​​​}

–CSV Parser ASOC ver (Translated from “ASObjCExtras.framework” Objective-C version)
on makeListsFromCSV:theString commaIs:theComma
  
  
set theRows to {} –最終的に出力するデータ(2D Listになる)
  
  
set newLineCharSet to current application’s NSCharacterSet’s newlineCharacterSet() –改行キャラクタ
  
set importantCharSet to current application’s NSMutableCharacterSet’s characterSetWithCharactersInString:(“\”" & theComma) –カンマ
  
  
importantCharSet’s formUnionWithCharacterSet:newLineCharSet
  
  
set theNSScanner to current application’s NSScanner’s scannerWithString:theString
  
theNSScanner’s setCharactersToBeSkipped:(missing value)
  
  
  
–データ末尾を検出するまでループ
  
repeat while (theNSScanner’s isAtEnd() as integer = 0)
    
    
set insideQuotes to false
    
set finishedRow to false
    
set theColumns to {}
    
set currentColumn to “”
    
    
–すべての行を処理終了するまでループ(行内部の処理)
    
repeat while (not finishedRow)
      
      
set {theResult, tempString} to theNSScanner’s scanUpToCharactersFromSet:importantCharSet intoString:(reference)
      
–log {”theResult”, theResult, “tempString”, tempString}
      
      
if theResult as integer = 1 then set currentColumn to currentColumn & (tempString as text)
      
–log {”currentColumn”, currentColumn}
      
      
–データ末尾検出
      
if theNSScanner’s isAtEnd() as integer = 1 then
        if currentColumn is not “” then set end of theColumns to currentColumn
        
set finishedRow to true
        
      else
        –データ末尾ではない場合
        
set {theResult, tempString} to theNSScanner’s scanCharactersFromSet:newLineCharSet intoString:(reference)
        
        
if theResult as integer = 1 then
          
          
if insideQuotes then
            –ダブルクォート文字内の場合
            
set currentColumn to currentColumn & (tempString as text)
          else
            –ダブルクォート内ではない場合
            
if currentColumn is not “” then set end of theColumns to currentColumn
            
set finishedRow to true
          end if
          
        else
          –行末文字が見つからない場合
          
set theResult to theNSScanner’s scanString:“\”" intoString:(missing value)
          
          
if theResult as integer = 1 then
            –ダブルクォート文字が見つかった場合
            
if insideQuotes then
              –ダブルクォート文字内の場合
              
set theResult to theNSScanner’s scanString:“\”" intoString:(missing value)
              
              
if theResult as integer = 1 then
                set currentColumn to currentColumn & “\”"
              else
                set insideQuotes to (not insideQuotes)
              end if
            else
              –ダブルクォート文字内ではない場合
              
set insideQuotes to (not insideQuotes)
            end if
            
          else
            –ダブルクォート文字が見つからなかった場合
            
set theResult to theNSScanner’s scanString:theComma intoString:(missing value) –カンマの検索
            
            
if theResult as integer = 1 then
              if insideQuotes then
                set currentColumn to currentColumn & theComma
              else
                set end of theColumns to currentColumn
                
set currentColumn to “”
                
theNSScanner’s scanCharactersFromSet:(current application’s NSCharacterSet’s whitespaceCharacterSet()) intoString:(missing value)
              end if
            end if
          end if
        end if
      end if
      
    end repeat
    
    
if (count of theColumns) > 0 then set end of theRows to theColumns –行データ(1D List)をtheRowsに追加(2D List)
    
  end repeat
  
  
return theRows
  
end makeListsFromCSV:commaIs:

★Click Here to Open This Script 

2015/03/11 CSVファイルをListにParseする(ASOC)

Shane Stanley wrote me a simple but strong AppleScriptObjC (ASOC) Script. It is a perfect one!

I checked Objective-C version csv parser. But they are not so short as this.

And I understood that this method was made just for this purpose:-).

csv2.png
▲Test Data

AppleScript名:CSVのParse 4(ASOC)
– Created 2015-03-11 by Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”

set someString to read (choose file)

set theData to current application’s SMSFord’s arrayFromCSV:someString commaIs:“,”
set theData to (current application’s SMSFord’s subarraysIn:theData paddedWith:“” |error|:(missing value)) as list
–>  {​​​​​{​​​​​​​”cust1″, ​​​​​​​”prod,1″, ​​​​​​​”season 1″, ​​​​​​​”"​​​​​}, ​​​​​{​​​​​​​”cust1″, ​​​​​​​”prod1″, ​​​​​​​”season 2″, ​​​​​​​”"​​​​​}, ​​​​​{​​​​​​​”cust2″, ​​​​​​​”prod1″, ​​​​​​​”event1″, ​​​​​​​”season 1″​​​​​}, ​​​​​{​​​​​​​”cust2″, ​​​​​​​”prod2″, ​​​​​​​”event1″, ​​​​​​​”season 2″​​​​​}, ​​​​​{​​​​​​​”cust2″, ​​​​​​​”prod3″, ​​​​​​​”event1″, ​​​​​​​”season 1″​​​​​}​​​}

★Click Here to Open This Script 

2015/03/11 CSVファイルをListにParseする

CSV file parsing AppleScript (CSV-> List of List) is familiar with us. We fix and fix specifications and make things easier.

But the data from real end-users are very irregular and unforcastable. So, I made such a irregular data and check many AppleScript routines.

csv1.png

csv2.png

Parser #1: By Skeeve42@gmx.net 2008/1/24
–> {{“cust1,\”prod,1\”,season 1,cust1,prod1,season 2,cust2,prod1,event1,season 1cust2,prod2,event1,season 2cust2,prod3,event1,season 1″}}–All items are concatenated :-(
Result: NG

Parser #2:By Gary (Lists) 2008/1/25
–> {{”cust1″, “prod,1″, “season 1″, “”}, {”cust1″, “prod1″, “season 2″, “”}, {”cust2″, “prod1″, “event1″, “season 1″}, {”cust2″, “prod2″, “event1″, “season 2″}, {”cust2″, “prod3″, “event1″, “season 1″}}
Result: OK

Parser #3: By BareFeet 2008/1/23
–> {{”cust1″, “\”prod”, “1\”", “season 1″, “”}, {”cust1″, “prod1″, “season 2″, “”}, {”cust2″, “prod1″, “event1″, “season 1″}, {”cust2″, “prod2″, “event1″, “season 2″}, {”cust2″, “prod3″, “event1″, “season 1″}}
Result: NG

Parser #2 seems the best to use and the worst to understand….his local accent is very hard. Maintainance cost may increase….

—————–Japanese

CSVファイルをListにParseするAppleScriptは割とありふれた処理ですが、いろいろと事前のチェックと仕様を決めることで、処理そのものを簡単で済むようにしています。

しかし、実際のエンドユーザーが作るデータはイレギュラーで予測不能なものになることがあります。そこで、イレギュラーなデータをExcel上で作成してCSV書き出しを行い、さまざまなAppleScriptのルーチンで試してみました。

Excel 2011で書き出してみたら、ファイルのテキストエンコーディングがUTF-8、改行コードがCRとなっていました。これを前提にしていますが、自動テキストエンコーディング判定ルーチンなどを併用して、安全にデータ読み込みするとよさそうです。

・・・Parser #2の結果が良好だったので、これを使うのがよさそうです。ただ、癖が強くて全然読めません(ーー;; 今後のOSのバージョンアップで期待の動作をしなくなったときに、書き直すときのコストが大きそう、、、

AppleScript名:CSVのParse 1
–By Skeeve42@gmx.net
–2008/1/24

on run
  set started to current date
  
set {oAStid, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, “|”}
  
set LoL to {}
  
repeat with rec in every paragraph of convert(choose file)
    copy text items of rec to the end of LoL
  end repeat
  
set AppleScript’s text item delimiters to oAStid
  
set stopped to current date
  
–return “Seconds elapsed: ” & (stopped - started)
  
return LoL
  
–> {{”cust1,\”prod,1\”,season 1,cust1,prod1,season 2,cust2,prod1,event1,season 1cust2,prod2,event1,season 2cust2,prod3,event1,season 1″}}
end run

to convert(a_file)
  return do shell script “perl -pe ’tr/\\012\\015//d; $_.=$/’ “ & quoted form of POSIX path of a_file
end convert

★Click Here to Open This Script 

AppleScript名:CSVのParse 2
set a to choose file
set b to read a
set aRes to |csv as list| from b
–> {{”cust1″, “prod,1″, “season 1″, “”}, {”cust1″, “prod1″, “season 2″, “”}, {”cust2″, “prod1″, “event1″, “season 1″}, {”cust2″, “prod2″, “event1″, “season 2″}, {”cust2″, “prod3″, “event1″, “season 1″}}

–”Gary (Lists)”
–2008/1/25
on |csv as list| from t
  
  
set d to text item delimiters
  
set u to “:”
  
set text item delimiters to u
  
  
repeat until (count t’s text items) is 1
    set u to u & u
    
set text item delimiters to u
  end repeat
  
  
set q to “q” & u
  
set p to “p” & u
  
set c to “c” & u
  
  
set text item delimiters to “\”\”"
  
set t to t’s text items
  
set text item delimiters to q
  
tell t to set t to beginning & ({“”} & rest)
  
set text item delimiters to “\”"
  
  
script o
    property l : t’s text items
    
    
on value_separator(e)
      repeat with i from 1 to e by 2
        tell l’s item i to if (count) > 0 then considering case
          if “,” is in it then
            return “,”
          else if “;” is in it then
            return “;”
          end if
        end considering
      end repeat
      
set text item delimiters to d
      
      
error “No value separator was identified.”
      
    end value_separator
  end script
  
  
set e to count o’s l
  
set s to o’s value_separator(e)
  
  
repeat with i from 1 to e by 2
    set text item delimiters to s
    
set t to text items of o’s l’s item i
    
set text item delimiters to c
    
tell t to set t to beginning & ({“”} & rest)
    
set text item delimiters to p
    
tell t’s paragraphs to set o’s l’s item i to beginning & ({“”} & rest)
  end repeat
  
  
set text item delimiters to “”
  
tell o’s l to set t to beginning & ({“”} & rest)
  
set text item delimiters to q
  
set o’s l to t’s text items
  
set text item delimiters to “\”"
  
tell o’s l to set t to beginning & ({“”} & rest)
  
set text item delimiters to p
  
set o’s l to t’s text items
  
set text item delimiters to c
  
  
repeat with i from 1 to count o’s l
    set o’s l’s item i to text items of o’s l’s item i
  end repeat
  
  
set text item delimiters to d
  
return o’s l
end |csv as list|

★Click Here to Open This Script 

AppleScript名:CSVのParse 3
set a to choose file
set b to read a
CsvToListOfText(b, “,”, “\\”, return) of me
–> {{”cust1″, “\”prod”, “1\”", “season 1″, “”}, {”cust1″, “prod1″, “season 2″, “”}, {”cust2″, “prod1″, “event1″, “season 1″}, {”cust2″, “prod2″, “event1″, “season 2″}, {”cust2″, “prod3″, “event1″, “season 1″}}

(*  CsvToListOfText 2008
  BareFeet http://www.tandb.com.au
  with a lot of help from Kai
  t = the text to parse
  delimiterString = the string to delimit items in a row, usually a comma
  quoteString = the string to wrap around items containing delimiters, usually a double quote. null if no quotes (faster).
  newLineString = the string to delimit the end of each line, usually a linefeed
*)

on CsvToListOfText(t, delimiterString, quoteString, newLineString)
  if t is in {“”, null} then
    return t
  else
    set oldDelimiters to text item delimiters
    
    
if quoteString is null then
      set text item delimiters to newLineString
    else – if quoteString is not null then
      
      
set quoteSubstitute to
      
set quote2Substitute to
      
set newLineSubstitute to
      
set delimiterSubstitute to
      
      
repeat with findSubstitutePair in {{delimiterString & quoteString, delimiterString & quoteSubstitute}, {newLineString & quoteString, newLineString & quoteSubstitute}, {quoteString & quoteString, quote2Substitute}, {quoteSubstitute, quoteString}}
        set {findString, substituteString} to findSubstitutePair
        
set text item delimiters to findString
        
set t to text items in t
        
set text item delimiters to substituteString
        
set t to t as string
      end repeat
      
      
set text item delimiters to quoteString
    end if
    
    
script listHandler
      property l : t’s text items
    end script
    
    
if quoteString is null then
      set text item delimiters to delimiterString
    else
      repeat with i from 1 to count listHandler’s l by 2
        set text item delimiters to delimiterString
        
set t to text items of listHandler’s l’s item i
        
set text item delimiters to delimiterSubstitute
        
set t to t as string
        
        
set text item delimiters to newLineString
        
set t to t’s text items
        
set text item delimiters to newLineSubstitute
        
set listHandler’s l’s item i to t as string
      end repeat
      
set text item delimiters to “”
      
set t to listHandler’s l as string
      
      
set text item delimiters to quote2Substitute
      
set listHandler’s l to t’s text items
      
set text item delimiters to quoteString
      
set t to listHandler’s l as string
      
      
set text item delimiters to newLineSubstitute
      
set listHandler’s l to t’s text items
      
set text item delimiters to delimiterSubstitute
    end if – quoteString is not null
    
repeat with i from 1 to count listHandler’s l
      set listHandler’s l’s item i to text items of listHandler’s l’s item i
    end repeat
    
set text item delimiters to oldDelimiters
    
return listHandler’s l
  end if – t is not in {”",null}
end CsvToListOfText

★Click Here to Open This Script 

2015/03/09 パワーユーザー向けWebブラウザ「Vivaldi」をコントロール

vi1.png

I had several trial to control Vivaldi freeware web browser (Technology Preview version 2) from AppleScript. I found it scriptable and has a Chromium based AppleScript dictionary. Almost of functions work, but some functions does not work (ex. enter presentation mode/exit presentation mode). Yes, this is just a Technical Preview, not a release version.

フリーのWebブラウザ「Vivaldi」(テクノロジープレビュー2版)がAppleScriptに対応していることを見つけたので、いろいろ試してみました。

vi2.png

ChromiumベースのAppleScript用語辞書を備えていますが、まだフルスクリーンモードを呼び出せないとか、機能的に不完全な印象です(Technology Preview版なので当然、、、)。全体的に、動作が軽快な印象を受けます。

AppleScript名:Vivaldiにアクセス実験
tell application “Vivaldi”
  activate
  
set dCount to count every window
  
  
tell window 1
    properties
    
–> {zoomable:true, closeable:true, zoomed:false, active tab index:1, class:window, index:1, visible:true, name:”Vivaldi”, miniaturizable:true, mode:”normal”, active tab:tab id 2 of window id 1, id:1, miniaturized:false, resizable:true, bounds:{38, 25, 940, 1158}, presenting:false}
    
    
– window’s mode :normal / incognito
    
    
tell active tab
      properties
      
–> {URL:”http://piyocast.com/as/”, name:”AS Hole(AppleScriptの穴) By Piyomaru Software”, loading:false, class:tab, id:2}
      
      
view source
      
    end tell
  end tell
  
enter presentation mode
end tell

★Click Here to Open This Script 

AppleScript名:Vivaldiで本文すべてコピー(テキスト)
tell application “Vivaldi”
  tell window 1
    tell active tab
      select all
      
copy selection
    end tell
  end tell
end tell

the clipboard

★Click Here to Open This Script 

AppleScript名:VivaldiでBookmark itemにアクセス
tell application “Vivaldi”
  properties of bookmark folders
  
–> {{name:”その他のブックマーク”, class:bookmark folder, id:2, index:2}, {name:”ブックマーク バー”, class:bookmark folder, id:1, index:1}}
  
set bCount to count every bookmark folder
  
  
repeat with i from 1 to bCount
    tell bookmark folder i
      set bList to every bookmark item
    end tell
  end repeat
end tell

★Click Here to Open This Script 

2015/03/06 ワイルドカードでSafariのダウンロードフォルダ中のファイルを抽出

This AppleScript gets pattern-matched file names in Safari’s Download folder.

Safariのダウンロードフォルダ中のファイルから、与えられたパターンに該当するファイル名のリストを取得するAppleScriptです。

(2015/8/10更新)チルダ付きのパスをechoコマンドで展開していたので、ASOC版のルーチンに差し替えました。

AppleScript名:ワイルドカードでSafariのダウンロードフォルダ中のファイルを抽出 v2
– Created 2015-03-06 by Takaaki Naganoya
– Created 2015-08-10 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

–Get Safari Download Folder Path
set downloadFolder to POSIX path of getSafariDownloadFolder()

–Make Filtering Predicates with WIldcard
set matchPattern to current application’s NSString’s stringWithString:“*.zip” –can use “*” , “?”
set aPredicate to current application’s NSPredicate’s predicateWithFormat_(“SELF like %@”, matchPattern)

–Get every file name in Safari Download Folder
set aFM to current application’s NSFileManager’s defaultManager()
set aConArray to aFM’s contentsOfDirectoryAtPath:downloadFolder |error|:(missing value)

–Filtering with Predicates
set aResArray to aConArray’s filteredArrayUsingPredicate:aPredicate
set aResList to aResArray as list
–>  {”33_fusagamepad_0.3.zip”, “expressmaci.zip”, “filer6.6.zip”, “Glyphs2.1.1-768.zip”, “LinCastor.zip”, “recordpadmaci.zip”, “TessOCR-1.08.zip”, “wavepadmaci.zip”}

–Safariのダウンロードフォルダーを取得する–Updated
on getSafariDownloadFolder()
  set theID to id of application “Safari” –> “com.apple.Safari”
  
set storedDefaults to (current application’s NSUserDefaults’s standardUserDefaults()’s persistentDomainForName:theID)
  
set downloadFolder to storedDefaults’s valueForKeyPath:“DownloadsPath.stringByExpandingTildeInPath”
  
return downloadFolder as «class furl»
end getSafariDownloadFolder

★Click Here to Open This Script 

2015/03/05 特定フォルダの更新通知を受け、特定ファイルが存在しているかを確認

I made an AppleScript program to download data file by using Safari. And the program detect the downloaded file then rename it and move it to another folder.

The program use OS built-in Folder Action Script mechanism (well known). Main program and Folder Action Script has a simple sync way using a plist to share the renaming rule and the state of renaming (finished or not). So, programs have to access the plist very frequently.

But sometimes Finder crashed. So, the process has been stopped.

I had to study another way to detect downloaded file. Notification seems very smart. Except FSEvents have to use blocks construction which can not be written in AppleScriptObjC.

This ASOC on Xcode project is originally written by StefanK@MacScripters. I changed a little (ARC etc.).

——-

Safariを使ってデータファイルをダウンロードするAppleScriptを作成。同プログラムは、Folder Action Scriptを使ってダウンロードされたファイルを検出し、リネームしたうえで別フォルダに移動するようになっていました。

しかし、ときどきFinderがクラッシュし(Yosemiteなのに搭載メモリーが4GBと少ないことが原因か?)、そのためにダウンロード検出を行えずに処理が止まることがあり、ファイルのダウンロード検出を行う別の仕組みを検討する必要に迫られました(ASOCでWebブラウザを作ることも検討したものの、あまり問題の解決にならず、、、)。

オリジナルのASOC on Xcodeのプログラムは、MacScriptersのStefanK氏が作ったものです。ARCに対応させるためにObjective-Cのプログラムを少しだけ書き換えました。

ご注意:本Script内ではSafariのダウンロードフォルダの設定ファイルから実際のパスを求めるさいにechoコマンドによるチルダの展開を行っていますが、ASOCによる展開に差し替えてご利用ください。

→ Download Xcode Project (33KB)

AppleScript名:AppDelegate

– AppDelegate.applescript
– dirWatcher

– http://macscripter.net/viewtopic.php?pid=161125
– Created by StefanK on 2013-03-11 02:05:32 am

– Changed by Takaaki Naganoya on 2015-03-05
– Copyright (c) 2015年 Takaaki Naganoya. All rights reserved.

script AppDelegate
  
  
property parent : class “NSObject”
  
  
property DirectoryWatcher : class “FSEDirectoryWatcher”
  
  
property statusImage1 : missing value – image view 1
  
property statusImage2 : missing value – image view 2
  
  
property watchFileName : “” –File Name to detect the existence
  
  
  
on applicationWillFinishLaunching:aNotification
    
    
set my watchFileName to “logfile0.log”
    
    
–Get Safari Download Folder Path
    
set preferencesPath to POSIX path of (path to preferences)
    
set bundleId to bundle identifier of (info for (path to application “Safari”))
    
set safariPrefsFile to preferencesPath & bundleId & “.plist”
    
tell application “System Events” to set folderName to get value of property list item “DownloadsPath” of property list file safariPrefsFile
    
tell current application
      set downloadFolder to (do shell script “echo “ & folderName)
    end tell
    
    
    
–Set Watch Folder Path
    
set hotFolder to current application’s NSString’s stringWithString:downloadFolder
    
directoryDidChange_(hotFolder)
    
set watcher to DirectoryWatcher’s directoryWatcherWithPath:hotFolder delegate:me
    
    
watcher’s start()
    
  end applicationWillFinishLaunching:
  
  
  
on directoryDidChange:directoryPath
    
    
set filePath to directoryPath’s stringByAppendingPathComponent:(my watchFileName)
    
set fileExists to (current application’s NSFileManager’s defaultManager()’s fileExistsAtPath:filePath) as boolean
    
    
log {“fileExists”, fileExists}
    
  end directoryDidChange:
  
  
end script

★Click Here to Open This Script 

2015/03/05 Game ControllerをAppleScriptランチャーにするMyJoystick

163e5c68-3e4b-428d-9944-b5d5952fd1b5.jpg

This utility was found on Mac AppStore. I was not aware of this because we could not find this by a keyword “AppleScript”.

img_2833.JPG

MyJoystick (100 yen) can execute AppleScript from PlayStation 3 or Xbox 360 wireless game controllers. Such a kind of bluetooth game controllers can connect with Mac computers.

btdevices.png

MyJoystick can assign AppleScript to each game controller buttons (one to one). Really it works.

mj1.png

mj2.png

mj3.png

mj4.png

You can download trial version of MyJoystick. It works for 2 minutes just for test.

Pros.
Cheap AppleScript launcher (100 yen) if you have PS3/Xbox 360 game controllers
Works in background

Cons.
We have to assign AppleScript by using copy & paste operation.It is dull operation…
There is no function to display name of each AppleScript (soon I forgot…)
There is no “AppleScript” tag on Mac App Store. It is hard to find.

—–

Mac App Storeで「MyJoystick」なるAppleScriptランチャーのUtilityをみつけました(100円)。本Utilityには「AppleScript」のタグがついていなかったので、Mac AppStore上で「AppleSciript」のキーワードで検索しても見つかりませんでした(NASNEのアプリがあるか探そうと、たまたま”SONY”のキーワードで偶然みつかった)。

My JoystickはXbox 360/PlayStation 3のワイヤレスゲームコントローラー(Bluetooth接続)でAppleScriptの起動を可能にするものです。それらのゲームコントローラーは、Macに無線でつなぐことが可能です(いったんUSBケーブルでMac本体につなぐ、といった操作は必要)。

MyJoystickはゲームコントローラーの各ボタンにAppleScriptを(コピー&ペーストで)割り当てることができ、実際に実行できます。

実際に使えるかどうか、お試し版(2分間だけ動作)を作者のホームページからダウンロードできます

いいところ:
・ゲームコントローラーが100円とたいへんお安い値段でAppleScriptランチャーになる(Xbox 360/PS3を持っていれば)
・バックグラウンド動作を行える

よくないところ:
・コピーペーストでAppleScriptを割り当てるのがダルい
・どのScriptをどのボタンに割り当てたか忘れるので、名称を確認できる機能はほしい(コピペしたAppleScriptの内容を確認する機能はある)
・Mac AppStoreに登録されているタグ情報に「AppleScript」はつけておくべき

ゲームコントローラーの「PS」ボタンを押すと画面上に割り当てたAppleScriptの名前が表示され、各ボタンへのAppleScriptの割り当てをAppleScript書類のドラッグ&ドロップで行うようになっていたら、200円でも買うかも(コピペは勘弁して)。

2015/03/04 Safariでオープン中のURLをリロードする

This AppleScript reloads frontmost Safari window.

本AppleScriptはSafariの最前面のウィンドウをリロード(再読み込み)するものです。

AppleScript名:Safariでオープン中のURLをリロードする
tell application "Safari"
  if (count every document) > 0 then
    do JavaScript "location.reload();" in front document
  end if
end tell

★Click Here to Open This Script 

2015/03/04 現在地点の緯度経度情報を取得する

This AppleScript get current location of your Mac by using CoreLocation. There is need to enable WiFi to get location using this AppleScript.

You can get altitude, timestamp, speed and course easily. But latitude and longitude were difficult to get.

I asked to Shane how to do this. His answer is “get description”.

You must execute this AppleScript in foreground. Original Script is made for a part of ASOC project on Xcode.

loc1.png
▲システム環境設定の「セキュリティとプライバシー」でScript EditorもしくはASObjC Explorer 4に位置情報の取得を許可しておく必要があります

loc2.png
▲許可しないとエラーが表示されます

本AppleScriptはお使いのMacの現在位置の緯度経度情報を取得するものです。CoreLocationを用いて、高度、タイムスタンプ、スピード、進行方向については容易に取得できました(位置情報を取得するためにWiFiをオンにしておく必要あり)。ただ、肝心の緯度経度情報だけはなかなか取得できず、Shaneに聞いてみたところ・・・「descriptionを取得しろ」とのこと(サンプルつきで)。

本AppleScriptの実行時には、foregroundで明示的に実行させる必要があります。オリジナルのScriptはASOC on Xcodeの一部として書いたもので、位置情報の取得/許可については本Scriptの方がうまくいっていない感じです(ASObjC Explorerがコケたりする)。

AppleScript名:GetCurrentLocation_Yosemite v3
– Created 2015-03-04 by Takaaki Naganoya, Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”
use framework “CoreLocation”
use framework “AppKit”

property curLatitude : 0
property curLongitude : 0

on run
  startStandardUpdates()
end run

on startStandardUpdates()
  –Listing 1-1 Starting the standard location service
  
set locationManager to current application’s CLLocationManager’s alloc()’s init()
  
  
set locE to locationManager’s locationServicesEnabled()
  
if (locE as boolean) = true then
    locationManager’s setDelegate:me
    
locationManager’s setDesiredAccuracy:(current application’s kCLLocationAccuracyNearestTenMeters)
    
locationManager’s setDistanceFilter:500
    
locationManager’s startUpdatingLocation()
  end if
  
end startStandardUpdates

on locationManager:manager didUpdateLocations:locations
  
  
–Listing 1-3 Processing an incoming location event
  
set location to (locations’s lastObject())
  
set eventDate to (location’s timestamp())
  
set howRecent to (eventDate’s timeIntervalSinceNow())
  
  
–Calc ABS
  
set howRecent to howRecent as real
  
set howRecent to absNum(howRecent)
  
  
if howRecent < 15.0 then
    
    
set alt to location’s altitude
    
–>  (NSNumber) 46.356517791748
    
    
set aSpeed to location’s speed
    
–>  (NSNumber) -1.0
    
    
set aCourse to location’s course –North:0, East:90, South:180, West:270
    
–>  (NSNumber) -1.0
    
    
–By Shane Stanley
    
set theDescription to location’s |description|()
    
–> (NSString) “< +35.xxxxx,+139.xxxxxx> +/- 65.00m (speed -1.00 mps / course -1.00) @ 2015/03/04 8時56分41秒 日本標準時”
    
    
set anNSScanner to current application’s NSScanner’s scannerWithString:theDescription
    
anNSScanner’s setCharactersToBeSkipped:(current application’s NSCharacterSet’s characterSetWithCharactersInString:“< ,")
    
set {theResult, aLat} to anNSScanner’s scanDouble:(reference)
    
set {theResult, aLng} to anNSScanner’s scanDouble:(reference)
    
    
copy {aLat, aLng} to {my curLatitude, my curLongitude}
    
  else
    stopUpdatingLocation()
  end if
  
end locationManager:didUpdateLocations:

on locationManager:anCLLocationManager didFailWithError:anNSError
  display dialog (anNSError’s localizedDescription() as text)
end locationManager:didFailWithError:

on absNum(aNum)
  if aNum > 0 then
    return aNum
  else
    return (aNum * -1)
  end if
end absNum

★Click Here to Open This Script 

2015/03/03 2点間の距離を求める v3

Shane Stanley wrote me the easier way to get distance of two places. I think easier way is better, too.

Shane Stanleyから「もっと楽な方法があるよ」と教えてもらいました。自分も簡単な方がいいと思います(^ー^;

AppleScript名:Calc Distance between 2 places v3
– Created 2015-03-03 by Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “CoreLocation”

set aPlace to current application’s CLLocation’s alloc()’s initWithLatitude:35.737072 longitude:139.637826
set bPlace to current application’s CLLocation’s alloc()’s initWithLatitude:35.753108 longitude:139.595123
set distanceInMetres to aPlace’s distanceFromLocation:bPlace
–>  4252.71123319014

★Click Here to Open This Script 

2015/03/03 2点間の距離を求める

This AppleScript calculates the distance (km) between 2 places. Place data is a pair of Latitude and Longitude.

This Script requires ASObjCExtras Framework.

dist.png

2点間の距離を求めるAppleScriptです(単位:km)。位置情報は緯度と経度のペアで与えます。実行には、ASObjCExtras Frameworkのインストールが必要です。

AppleScript名:Calc Distance between 2 places v2
– Created 2015-03-03 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "ASObjCExtras"

set aPlace to {latitude:35.737072, longitude:139.637826} –Seibu-Ikebukuro Line Nakamurabashi Station (My Nearest Station)
set bPlace to {latitude:35.753108, longitude:139.595123} –Amusium OSC (Game Center, Nearest Senjo-No-Kizuna POD)

set aDistance to calcDistanceBetweenPlaces(aPlace, bPlace)
–>  4.251157707731 (km)

–2点間の距離を計測する(km単位)
–参考:http://log.nissuk.info/2012/04/2.html
on calcDistanceBetweenPlaces(aPlace, bPlace)
  
  
set r to 6378.137 –Equatorial radius/赤道半径(km)
  
  
–Place A
  
set lat1 to (latitude of aPlace) * pi / 180
  
set lng1 to (longitude of aPlace) * pi / 180
  
  
–Place B
  
set lat2 to (latitude of bPlace) * pi / 180
  
set lng2 to (longitude of bPlace) * pi / 180
  
  
–Calculation
  
set calc1 to (current application’s SMSFord’s sinValueOf:lat1) as real
  
set calc2 to (current application’s SMSFord’s sinValueOf:lat2) as real
  
  
set calc3 to (current application’s SMSFord’s cosValueOf:lat1) as real
  
set calc4 to (current application’s SMSFord’s cosValueOf:lat2) as real
  
  
set calc5 to (current application’s SMSFord’s cosValueOf:(lng2 - lng1)) as real
  
  
set aDist to (current application’s SMSFord’s acosValueOf:(calc1 * calc2 + calc3 * calc4 * calc5)) as real
  
set aDist to aDist * r
  
  
return aDist
  
end calcDistanceBetweenPlaces

★Click Here to Open This Script