Archive for the 'Script Editor/AppleScript Editor' Category

01/14 ドロップされたASをTextWranglerでdiff表示

ドロップされたAppleScriptをTextWrangler(version 3.5.3)でdiff表示するAppleScriptです。他のAppleScriptのファイルを処理してdiff表示(差分表示)を行うユーティリティ的なものです。

以前に、「ドロップされたASをdiff表示 Mac OS X 10.4対応版」というものを作ったことがありました。AppleScriptをdiff表示するのに、普通はApple純正のFileMergeを使っているのですが、そのためには文字コードなどの書き換えをする必要があり、TextWranglerを併用して……TextWrangler自体がdiff表示機能を持っていることを思い出し、TextWranglerでdiff表示させるというものでした。

すでに決着が付いたかのように思われていた、AppleScript業界の「diff問題」が再燃したのは、読者がいるんだかいないんだかさっぱり不明なこのBlogの、読者の方からの1通のメールからでした。

『いつもお世話になります。(サイトに)

希望といいますか要望だけで申し訳ないのですが、「ドロップされたASをdiff表示 Mac OS X 10.4対応版」の10.6対応版などを作ってはいただけないでしょうか?
というのも、10.6ならdiff表示v4で十分なはずなんですが、業務PCにてXcodeのインストールが許可されていないという事情がありまして、もしよろしければ、ご検討いただけますようお願いいたします。』

……「スクリプトエディタ」を操作していたところを「AppleScriptエディタ」に書き換えれば瞬殺ではないか、と思って手をつけてみたら……意外とたいへんでした(汗)

Mac OS X 10.6上でTextWranglerを使ってcompare fileコマンドでdiffを取ろうとすると……謎のエラーが出ます。

set oldPath to choose file
set newPath to choose file

set oldPath to oldPath as string
set newPath to newPath as string

tell application “TextWrangler”
  compare file oldPath against file newPath
end tell

こんな、最低限の基礎的な記述に戻してあげて(トラブル時にものすごく大事なやりかた)、テキストに書き出したAppleScriptを2つ指定してみると……あいかわらずエラーになります。

 「もう、TextWranglerじゃなくて別のツールでも使おうか……」

日も暮れて、そう考えかけたころ、「fileで指定しているのがいけないのでは?」と気付き、aliasで渡してみたら何事もなかったように表示されました。

tw_diff106.jpg

そもそも、TextWranglerのAppleScript用語辞書(アプリケーションのアイコンをAppleScriptエディタにドラッグ&ドロップすると表示)を見てみると、

twdic.jpg

などと書いてあるので、「そうかーaliasじゃダメなんだー」と受け取ったからです。これは、TextWranglerのAppleScript用語辞書が間違っています。

asdic.jpg

▲こんな風に書かなくては(AppleScriptエディタの用語辞書より「open」命令の記述)

このScriptをアプリケーション形式で保存し、出来上がったドロップレットに2つのAppleScript書類をドロップすると、TextWranglerでdiff表示を行います。

スクリプト名:asdiff
on run
  –環境確認を行うべき(書いてない)
  
  
–FileMergeの起動を最初にやっておく
  
tell application “System Events”
    set fmExists to (exists of process “TextWrangler”)
  end tell
  
  
if fmExists = false then
    tell application “TextWrangler”
      launch
    end tell
  end if
  
end run

on open fileList
  
  
tell application “Finder”
    set sortedList to sort fileList by creation date
  end tell
  
  
set sortedList to reverse of sortedList
  
  
set oldPath to writeASSourceToTempFolder((item 1 of sortedList) as alias)
  
set newPath to writeASSourceToTempFolder((item 2 of sortedList) as alias)
  
  
–do shell script “/usr/bin/opendiff ” & oldPath’s POSIX path’s quoted form & ” ” & newPath’s POSIX path’s quoted form & ” > /dev/null 2>&1 &”
  
  
tell application “TextWrangler”
    compare oldPath against newPath –Mac OS X 10.6用にaliasで渡すように書き換えた
  end tell
  
  
end open

–AppleScriptのソースを取得してファイルに書き出し
on writeASSourceToTempFolder(aScript)
  –ASのソースを取得
  
set scriptSource to getContentsOfScript(aScript) of me
  
if scriptSource = false then
    display dialog “指定のASのオープン時にエラーが発生”
    
return false –エラー
  end if
  
  
tell application “Finder”
    set origName to name of file aScript
  end tell
  
set origName to makestr_alphabetNumeric_only(origName) of me
  
  
  
–tmpにASのソースを一時ファイルとして保存
  
set tmpPath to (path to temporary items from system domain) as string
  
set aFN to do shell script “/bin/date +%Y%m%d_%H%M%S”
  
set tmpPathFull to tmpPath & origName & “_” & aFN & “.txt”
  
set fRes to write_to_file_UTF8(scriptSource, tmpPathFull, false) of me
  
if fRes = true then
    return tmpPathFull as alias –書き出したテキストのフルパスを返す(10.6用に変更)
  else
    return false –エラー
  end if
end writeASSourceToTempFolder

–指定したAppleScriptのソースを取得する(Mac OS X 10.4用)
on getContentsOfScript(aScript)
  tell application “AppleScript Editor”
    try
      with timeout of 600 seconds –アプリケーションの起動に時間がかかるケースもあるので180秒から延長
        set aScript to open aScript
      end timeout
    on error
      return false
    end try
    
    
tell window 1
      set aName to name
    end tell
    
    
tell document aName
      set aCon to contents
      
close without saving
    end tell
  end tell
  
  
return aCon
end getContentsOfScript

–ファイルへのUTF8での書き込み
on write_to_file_UTF8(this_data, target_file, append_data)
  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 as «class utf8» starting at eof
    
close access the open_target_file
    
return true
  on error
    try
      close access file target_file
    end try
    
return false
  end try
end write_to_file_UTF8

–アルファベットと数字のみの文字列にして返す
on makestr_alphabetNumeric_only(aKeyword)
  set aKeyword to aKeyword as string
  
set aKeyword to aKeyword as Unicode text
  
  
set cList to characters of aKeyword
  
set newName to “”
  
  
repeat with i in cList
    set aRes to checkAN(i) of me
    
if aRes = true then
      set newName to newName & (i as string)
    end if
  end repeat
  
  
return newName
end makestr_alphabetNumeric_only

on checkAN(aKeyword)
  set anList to {“a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”, “i”, “j”, “k”, “l”, “m”, “n”, “o”, “p”, “q”, “r”, “s”, “t”, “u”, “v”, “w”, “x”, “y”, “z”, “-”, “+”, “.”, “_”, “=”, “(”, “)”, “#”, “$”, “%”, “&”, “~”, “^”, “0″, “1″, “2″, “3″, “4″, “5″, “6″, “7″, “8″, “9″}
  
  
set aKeyword to aKeyword as Unicode text
  
set aKeyword to aKeyword as string
  
set kList to characters of aKeyword
  
repeat with i in kList
    ignoring case
      if i is not in anList then
        return false
      end if
    end ignoring
  end repeat
  
return true
end checkAN

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

05/05 ドロップされたASをdiff表示 Mac OS X 10.4対応版

ドロップされた2つのAppleScript書類のdiff表示を行うAppleScriptのMac OS X 10.4対応版です。

まず、本AppleScriptを実行形式で保存(ドラッグ&ドロップを受け付けるドロップレットになる)しておき、比較を行うAppleScript2本をそのドロップレットにドラッグ&ドロップします。

Mac OS X 10.4上でTextWlangerがインストールされていれば、スクリプトエディタ経由でテキストを受け取ってTextWrangler上でTextWranglerのビルトインのdiff機能を用いてdiff表示を行います。

tw1.jpg

FileMergeでdiff表示することも考えないではなかったのですが、結局テキスト処理のためにTextWranglerが必要になってしまい、

 「それなら、TextWranglerでdiff表示させたほうが……」

ということで、TextWranglerでdiff表示させた次第です。なお、現時点でBareBones SoftwareからダウンロードできるTextWranglerは最低でもMac OS X 10.5を必要とするため、Mac OS X 10.4対応のTextWranglerをすでに用意してある環境でのみの実行が可能です。

スクリプト名:asDiff3.10411
on run
  環境確認を行うべき(書いてない)
  
  
FileMergeの起動を最初にやっておく
  
tell application "System Events"
    set fmExists to (exists of process "TextWrangler")
  end tell
  
  
if fmExists = false then
    tell application "TextWrangler"
      launch
    end tell
  end if
  
end run

on open fileList
  
  
tell application "Finder"
    set sortedList to sort fileList by creation date
  end tell
  
  
set sortedList to reverse of sortedList
  
  
set oldPath to writeASSourceToTempFolder((item 1 of sortedList) as alias)
  
set newPath to writeASSourceToTempFolder((item 2 of sortedList) as alias)
  
  
do shell script "/usr/bin/opendiff " & oldPath’s POSIX path’s quoted form & " " & newPath’s POSIX path’s quoted form & " > /dev/null 2>&1 &"
  
  
tell application "TextWrangler"
    compare file oldPath against file newPath
  end tell
  
  
end open

AppleScriptのソースを取得してファイルに書き出し
on writeASSourceToTempFolder(aScript)
  ASのソースを取得
  
set scriptSource to getContentsOfScript(aScript) of me
  
if scriptSource = false then
    display dialog "指定のASのオープン時にエラーが発生"
    
return false エラー
  end if
  
  
tell application "Finder"
    set origName to name of file aScript
  end tell
  
set origName to makestr_alphabetNumeric_only(origName) of me
  
  
  
tmpにASのソースを一時ファイルとして保存
  
set tmpPath to (path to temporary items from system domain) as string
  
set aFN to do shell script "/bin/date +%Y%m%d_%H%M%S"
  
set tmpPathFull to tmpPath & origName & "_" & aFN & ".txt"
  
set fRes to write_to_file_UTF8(scriptSource, tmpPathFull, false) of me
  
if fRes = true then
    return tmpPathFull 書き出したテキストのフルパスを返す
  else
    return false エラー
  end if
end writeASSourceToTempFolder

指定したAppleScriptのソースを取得する(Mac OS X 10.4用)
on getContentsOfScript(aScript)
  tell application "Script Editor"
    try
      with timeout of 600 seconds アプリケーションの起動に時間がかかるケースもあるので180秒から延長
        set aScript to open aScript
      end timeout
    on error
      return false
    end try
    
    
tell window 1
      set aName to name
    end tell
    
    
tell document aName
      set aCon to contents
      
close without saving
    end tell
  end tell
  
  
return aCon
end getContentsOfScript

ファイルへのUTF8での書き込み
on write_to_file_UTF8(this_data, target_file, append_data)
  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 as «class utf8» starting at eof
    
close access the open_target_file
    
return true
  on error
    try
      close access file target_file
    end try
    
return false
  end try
end write_to_file_UTF8

アルファベットと数字のみの文字列にして返す
on makestr_alphabetNumeric_only(aKeyword)
  set aKeyword to aKeyword as string
  
set aKeyword to aKeyword as Unicode text
  
  
set cList to characters of aKeyword
  
set newName to ""
  
  
repeat with i in cList
    set aRes to checkAN(i) of me
    
if aRes = true then
      set newName to newName & (i as string)
    end if
  end repeat
  
  
return newName
end makestr_alphabetNumeric_only

on checkAN(aKeyword)
  set anList to {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "-", "+", ".", "_", "=", "(", ")", "#", "$", "%", "&", "~", "^", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
  
  
set aKeyword to aKeyword as Unicode text
  
set aKeyword to aKeyword as string
  
set kList to characters of aKeyword
  
repeat with i in kList
    ignoring case
      if i is not in anList then
        return false
      end if
    end ignoring
  end repeat
  
return true
end checkAN

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

08/10 Script Objectのparseのじっけん v4

AppleScriptのプログラムリストを解析して、Script Objectのリストアップを行うAppleScriptです。

AppleScriptのプログラムを解析する、自己解析系のAppleScriptを作りかけて……複数のAppleScript書類に存在しているハンドラ同士のdiffを取ろうとしていました。同じ名称のハンドラで、処理内容が異なる場合には困るので、比較しようと考えたわけです。

ハンドラ同士のDiffを取ろうと考えたときに、普通のハンドラなら簡単でよいのですが……

スクリプト名:script1
on test()
  display dialog “Test”
end test

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

ここに、Script Objectの宣言が加わってくると面倒です。さまざまな大きめのプログラムをつなげるときに、お互いにハンドラの重複があったりして統合が面倒という時があって、そういう時にはscript objectで論理分割して、同じハンドラ名称があっても別物扱いするようなことが……よくあります。

スクリプト名:script2
script scriptObj1
  on test()
    display dialog “Test”
  end test
end script

script scriptObj2
  on test()
    display dialog “Test”
  end test
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

このぐらいならまだかわいげがあるのですが、Script文は入れ子にできるので、これに対処する必要があります。

スクリプト名:script21
script scriptObj1
  on test()
    display dialog "Test@scriptObj1"
  end test
end script

script scriptObj2
  on test()
    display dialog "Test@scriptObj2"
    
    
script scriptObj21
      on test()
        display dialog "Test@scriptObj21"
      end test
      
script scriptObj211
        on testr()
          display dialog "Test@ scriptObj211"
        end testr
      end script
    end script
    
  end test
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

下のScriptをscript 21に対して実行すると、

–> {{”scriptObj1″, 1, 5}, {”scriptObj2″, 7, 23}, {”scriptObj21″, 11, 20}, {”scriptObj211″, 15, 19}}

といった結果が返ってきます。

このScript文を考慮してハンドラのリストアップを行うようにするといい感じでしょうか。

スクリプト名:Script Objectのparseのじっけん v4
–v4では、ネスティングしたScript文から再帰でオブジェクト名をピックアップ。一応の完全体
–v3では、Script文のネスティングに対応(ピックアップまで対応)
–v2では、Script文のネスティングに対応(対応しただけ)

global scObjList –このへん、必須(結果を値渡しではなく、グローバル変数へアクセスで行うため)
global aScriptList, a_r –ここも必須(再帰時にアクセスするのと、高速化のため)

–サンプルのAppleScript書類の内容をピックアップ
tell application “AppleScript Editor”
  set nameList to name of every document
  
set selDoc to choose from list nameList
  
tell document (contents of first item of selDoc)
    set a to contents
  end tell
end tell

set aScriptList to paragraphs of a
set a_r to a reference to aScriptList –間接アクセスで処理の高速化を行う

set allLen to length of a_r
set scObjList to {}

pickUpScriptObjectFromList(1, allLen) of me
set objList to shellSortListAscending(scObjList, 2) of me

objList

on pickUpScriptObjectFromList(startLineNum, endLineNum)
  
  
set curScriptObj to {} –name, startLine, endLiine
  
set nestingCounter to 0
  
set nestedF to false
  
set lineCounter to startLineNum
  
set findF to false –script object末尾検索フラグ。trueで末尾の”end script”の検索中
  
  
repeat with i from startLineNum to endLineNum
    
    
set ii to contents of (item i of a_r)
    
    
ignoring hyphens, punctuation and white space
      –Script文の開始位置を走査中
      
if findF = false then
        –Script文をみつけた場合
        
if ii begins with “script” then
          set aRes to parseScriptObjectName(ii) of me
          
set curScriptObj to {aRes, lineCounter, 0}
          
set findF to true
        end if
        
        
      else if findF = true then
        –Script文の末尾を走査中モード
        
if ii begins with “script” then
          set nestingCounter to nestingCounter + 1
          
set nestedF to true
          
        else if ii begins with “end script” then
          if nestingCounter = 0 then
            set item 3 of curScriptObj to lineCounter
            
set the end of scObjList to curScriptObj
            
            
if nestedF = true then
              –このへんで、Script Objectのネスティングに対して再帰でアプローチする
              
pickUpScriptObjectFromList((item 2 of curScriptObj) + 1, (item 3 of curScriptObj) - 1) of me –再帰時に捜索範囲を前後ともに1行ずつ狭める
            end if
            
            
set findF to false
            
set nestingCounter to 0
            
set nestedF to false
            
          else
            set nestingCounter to nestingCounter - 1
            
          end if
        end if
      end if
    end ignoring
    
    
set lineCounter to lineCounter + 1
    
  end repeat
end pickUpScriptObjectFromList

–与えられた1行分のテキスト(おそらく、script文の宣言部分)から、Script Object名称をparseする
on parseScriptObjectName(aText)
  set aOffst to offset of “script “ in aText
  
if aOffst = 0 then return “”
  
set aRes to text (aOffst + (length of “script “)) thru -1 of aText
  
return aRes
end parseScriptObjectName

–文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

–シェルソートで入れ子のリストを昇順ソート
on shellSortListAscending(a, keyItem)
  set n to length of a
  
set cols to {1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1}
  
repeat with h in cols
    if (h (n - 1)) then
      repeat with i from h to (n - 1)
        set v to item (i + 1) of a
        
set j to i
        
repeat while (j h) and ((contents of item keyItem of item (j - h + 1) of a) > (item keyItem of v))
          set (item (j + 1) of a) to (item (j - h + 1) of a)
          
set j to j - h
        end repeat
        
set item (j + 1) of a to v
      end repeat
    end if
  end repeat
  
return a
end shellSortListAscending

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

06/22 指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する 10.5_10.6

指定の文字列をAppleScriptとして評価して実行し、結果をすべて文字列で取得するAppleScript……の、Mac OS X 10.5/10.6の両バージョン対応版です。動作には、GUI Scriptingがオンになっている必要があります。

iChat経由でAppleScriptを実行するAppleScriptを作ったまでは良かったのですが、リモート環境にあるMacがMac OS X 10.5で稼働しており、10.5/10.6の両環境で動く必要が出てきました。

AppleScriptを記述したり生成用に使ったりするプログラムは、Mac OS X 10.5までは「スクリプトエディタ」、10.6からは「AppleScriptエディタ」という名前になっており、OSのバージョンを取得してGUI Scriptingでコントロールするパラメータを(ちょっとだけ)変更し、両プログラムのGUIのちがい(割り当てられたキーボードショートカットのキーが異なるとか)を吸収しています。

as106.jpg
▲Mac OS X 10.6上の「AppleScriptエディタ」の「表示」メニュー。「結果を表示」がCommand-3

as105.jpg
▲Mac OS X 10.5上の「スクリプトエディタ」の「表示」メニュー。「結果を表示」がCommand-2

とりあえず、10.4は対象にしなくてよさそうだったので10.4はサポートしていませんが、サポートしたい環境にいる方は、if文で10.4に対応させるといいかもしれません(そもそも、iChatのイベントでAppleScriptを動かす仕組みは10.5から導入されたので、あんまりうまみがありません)。

スクリプト名:指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する 10.5_10.6
set aScript to “tell app \”Finder\” to get properties of startup disk”
set asRes to getAppeScriptRes(aScript) of me

–指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する
on getAppeScriptRes(aScript)
  tell application id “com.apple.scripteditor2″
    make new document
    
tell window 1
      set bDoc to name
    end tell
    
    
tell document bDoc
      set contents to aScript
      
      
–いきなり実行する
      
try
        execute
      on error
        close without saving
        
return false
      end try
    end tell
    
  end tell
  
  
  
set osVer to system attribute “sys2″
  
  
–GUI Scripting経由でAppleScriptの実行結果を取得する
  
activate application id “com.apple.scripteditor2″
  
tell application “System Events”
    
    
if osVer > 5 then
      –Mac OS X 10.6以降の場合(とりあえず10.6.x)
      
tell process “AppleScript エディタ” –各国語環境で名前は違うかもしれない、と日本語で書いてみる
        keystroke “3″ using {command down} –command-3 結果を表示
        
set resVal to value of text area 1 of scroll area 1 of group 1 of group 1 of splitter group 1 of window 1
      end tell
      
    else if osVer = 5 then
      –Mac OS X 10.5の場合
      
tell process “スクリプトエディタ” –ここも各言語環境で名前が違う、と日本語で書いてみる
        keystroke “2″ using {command down} –command-2 結果を表示
        
set resVal to value of text area 1 of scroll area 1 of group 1 of splitter group 1 of window 1
      end tell
    end if
  end tell
  
  
  
tell application id “com.apple.scripteditor2″
    tell document bDoc
      close without saving
    end tell
  end tell
  
  
return resVal
  
end getAppeScriptRes

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

06/17 指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する

指定したAppleScript文字列を、実際にAppleScriptエディタ上で実行して、その結果を「文字列として」取得するAppleScriptです。

一昨日掲載した大物AppleScriptにも、かなり不満が残っていました。それは、「as:」とAppleScriptコマンドを実行させても、結果が文字化けして返ってくることがあることです。各アプリケーション依存のオブジェクト値だったりすると、無理やり文字列に直そうとしても、

“{class:«class cdis», name:\”Cherry\”, index:2, displayed name:\”Cherry\”, name extension:\”\”, extension hidden:false, «class ctnr»:«class pcmp» of application \”Finder\”, «class cdis»:«class sdsk» of application \”Finder\”, «class posn»:{98, 82}, «class dpos»:{1714, 37}, bounds:{66, 50, 130, 114}, kind:\”ボリューム\”, «class labi»:0, locked:false, «class dscr»:missing value, «class comt»:\”\”, size:5.33816377344E+11, «class phys»:5.33816377344E+11, creation date:date \”2010年2月20日土曜日 13:24:06\”, modification date:date \”2010年6月17日木曜日 11:00:56\”, «class iimg»:missing value, URL:\”file://localhost/\”, «class sown»:\”システム\”, «class sgrp»:\”admin\”, «class ownr»:«constant ****rdwr», «class gppr»:«constant ****rdwr», «class gstp»:«constant ****read», «class cwnd»:«class cwnd» of «class sdsk» of application \”Finder\”, id:-100, «class capa»:6.39791054848E+11, «class frsp»:1.05974677504E+11, «class isej»:false, «class istd»:true, «class dfmt»:«constant ****dfh+», «class Jrnl»:true, «class isrv»:true, «class igpr»:false} “

のように、残念な結果が得られてしまいます。

そこで、パーフェクトに指定のAppleScriptの実行結果を取得できる方法を検討してみました。

こういう用途になると、がぜん登場してくるのが、AS系のブラックテクノロジーともいえる「GUI Scripting」。将来の互換性とか、アプリケーションがバージョンアップしたら使えなくなるかもしれないとか、スピードがいまいちとか、そういうことにすべて目をつぶって「目的だけ果たせればそれでいい」という手段です。

前出の実行結果も、

“{class:disk, name:\”Cherry\”, index:2, displayed name:\”Cherry\”, name extension:\”\”, extension hidden:false, container:computer container of application \”Finder\”, disk:startup disk of application \”Finder\”, position:{98, 82}, desktop position:{1714, 37}, bounds:{66, 50, 130, 114}, kind:\”ボリューム\”, label index:0, locked:false, description:missing value, comment:\”\”, size:5.3381421056E+11, physical size:5.3381421056E+11, creation date:date \”2010年2月20日土曜日 13:24:06\”, modification date:date \”2010年6月17日木曜日 11:00:56\”, icon:missing value, URL:\”file://localhost/\”, owner:\”システム\”, group:\”admin\”, owner privileges:read write, group privileges:read write, everyones privileges:read only, container window:container window of startup disk of application \”Finder\”, id:-100, capacity:6.39791054848E+11, free space:1.05976844288E+11, ejectable:false, startup:true, format:Mac OS Extended format, journaling enabled:true, local volume:true, ignore privileges:false}”

……と、きちんと得られるようになり、「もうちょっと手を入れてみようか」と欲が出てきてしまうところです。

スクリプト名:指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する
set aScript to “tell app \”Finder\” to get properties of startup disk”
set asRes to getAppeScriptRes(aScript) of me

–指定文字列のAppleScriptをAppleScriptエディタ上で実際に実行して結果を文字列として取得する
on getAppeScriptRes(aScript)
  tell application “AppleScript Editor”
    make new document
    
tell window 1
      set bDoc to name
    end tell
    
    
tell document bDoc
      set contents to aScript
      
      
–いきなり実行する
      
try
        execute
      on error
        close without saving
        
return false
      end try
    end tell
    
  end tell
  
  
–GUI Scripting経由でAppleScriptの実行結果を取得する
  
activate application “AppleScript Editor”
  
tell application “System Events”
    tell process “AppleScript エディタ” –各国語環境で名前は違うかもしれない、と日本語で書いてみる
      keystroke “3″ using {command down} –command-3 結果を表示
      
set resVal to value of text area 1 of scroll area 1 of group 1 of group 1 of splitter group 1 of window 1
    end tell
  end tell
  
  
tell application “AppleScript Editor”
    tell document bDoc
      close without saving
    end tell
  end tell
  
  
return resVal
  
end getAppeScriptRes

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

12/26 選択文字列を伏せ字に

AppleScriptエディタ上で選択中の文字列を伏せ字に置き換えます(文字数は同じですべて「X」の文字)。

/Library/Scripts/Script Editor Scriptsフォルダ以下に入れて、AppleScriptエディタのコンテクストメニューから呼び出すことを前提に作成したものです。

AppleScriptエディタ上で文字列を選択しておき……

ed1.jpg

Controlキーを押しながらマウスクリック、あるいはマウスの副(右)ボタンをクリックしてコンテクストメニューを表示して、

ed2.jpg

メニューから本Scriptを実行すると……

ed21.jpg

選択部分が伏せ字になります。

ed3.jpg

スクリプト名:選択文字列を伏せ字に
tell application “AppleScript Editor”
  try
    tell document 1
      set ab to contents of selection
      
set aCount to length of ab
      
set outStr to “”
      
repeat aCount times
        set outStr to outStr & “X”
      end repeat
      
set contents of selection to outStr
    end tell
  end try
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

12/15 最前面のアプリケーションに対するAppleScriptを新規作成 v3

最前面のアプリケーションに対するAppleScriptを新規作成し、同アプリケーションの用語辞書をAppleScriptエディタでオープンするAppleScriptです。Script Menuに入れて使います。

as2.jpg

/Library/Scriptsフォルダ内に入れて使うことを前提にしています。ここに入れたScriptは、どのアプリケーションが前面に表示されていてもメニューに表示されます。

本Scriptを実行すると、最前面のアプリケーションに対するtellブロックのAppleScriptが新規作成され、同アプリケーションの用語辞書がAppleScriptエディタで表示され、AppleScriptエディタが一番前に表示されます。

as1.jpg

ただし、スクリプタブル「ではない」アプリケーションに対して実行したときのエラートラップが有効に機能しておらず、AppleScriptエディタでエラーがキャッチされて実行が止まってしまいます。こうなると、AppleScriptエディタを強制終了する必要があるため、気をつけてください。

System EventsとFinderを使って最前面のアプリケーションがAppleScriptに対応しているかどうかチェックしてから処理……というパターンも書いてみたものの、Scriptableでないクセに「has scripting terminology」がtrue(System Events/Finder)だったり、「accepts high level events」がtrue(Finder)だったりするアプリケーションがあった(iThink 9.1.3 Trial)ので、搭載を見送った経緯があります。

スクリプト名:最前面のアプリケーションに対するAppleScriptを新規作成 v3
tell application “System Events”
  set appList to every process whose frontmost is true
  
set anApp to first item of appList
  
set aName to name of first item of appList
  
set aFile to file of anApp
end tell

try
  tell application id “com.apple.ScriptEditor2″
    open aFile
  end tell
on error aMes
  –display dialog “アプリケーション「” & aMes & “」のAppleScript用語辞書のオープンを試みましたが、以下の理由により失敗しました:” & return & aMes
  
return
end try

set aCon to “tell application “ & (ASCII character 34) & aName & (ASCII character 34) & return & return & “end tell” & return

tell application id “com.apple.ScriptEditor2″
  set aNewDoc to make new document
  
tell document 1
    set contents to aCon
    
try
      compile
    end try
  end tell
  
activate
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

10/28 最前面のアプリケーションのAppleScript用語辞書をオープンする

最前面のアプリケーションのAppleScript用語辞書をオープンするAppleScriptです。

日常的に、「起動中のアプリケーションのAppleScript用語辞書をオープンする」という作業が多いので、これを手っ取り早く行うためのScriptを作成しました。

Script Menuに本Scriptを登録しておいて、呼び出すと……

as1.jpg

このように、最前面のアプリケーションのAppleScript用語辞書がオープンします(個別のアプリケーション用のScriptフォルダではなく、共通でMenuに表示されるフォルダ=「コンピュータ・スクリプト・フォルダ」(/Library/Scripts/)に入れておく必要があります)。Script Menuに入れる際に先頭にハイフン(「–」)を入れているのは、メニューの上の方に表示させるための小細工です。

as2.jpg

AppleScriptエディタ/スクリプトエディタへのtellブロックをアプリケーション名称ではなくIDで指定しているのは、OSのバージョンが10.5→10.6と変わったときに書き換えなくてもすむようにするためです。

実際には、10.5→10.6に移行したときに書き換える必要はなく、「スクリプトエディタはどこにあるか?」とOS側が聞いてくるので、AppleScript Editorを選択すればOS内でひもづけが行われます。ただ、本Blogに掲載しているようなリンクであるとか、テキストの状態になっているAppleScriptをコンパイル(構文確認)する場合には、アプリケーション名の書き換えが必要になってしまいます。そういうケースに備えてIDで指定した次第です。

スクリプト名:最前面のアプリケーションのAppleScript用語辞書をオープンする
tell application “System Events”
  set pList to name of every process whose visible is true and frontmost is true
end tell

set aRes to first item of pList

tell application “System Events”
  set aP to file of process aRes
end tell

try
  tell application id “com.apple.ScriptEditor2″
    open aP
  end tell
on error aMes
  display dialogアプリケーション「” & aRes & “」のAppleScript用語辞書のオープンを試みましたが、以下の理由により失敗しました:” & return & aMes
end try

tell application id “com.apple.ScriptEditor2″
  activate
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

01/08 スクリプトエディタがオープンしているウィンドウのうち、指定名称のものを最前面に出す

スクリプトエディタでオープンしているAppleScriptのうち、指定名称のものを最前面に出します。ただ、このAppleScriptをスクリプトエディタ上で実行すると、スクリプトエディタの制御がうまく行きません。

実際には、Script Menuに入れて実行するか……Script Debugger上から実行することになります。GUI Scriptingを使用しているため、システム環境設定のユニバーサルアクセスで「補助装置にアクセスできるようにする」チェックボックスをオンにしておく必要があります。

スクリプトの内容を書式つきのリッチテキストで取得したかったので、特定のScriptのウィンドウを最前面に出す必要があったのでした。本来の目的(Mindjet MindManagerのノート欄に書式つきでAppleScriptのリストを入れたかった)は果たせませんでしたが……残骸のサブルーチンはきっとどこかで何か別の用途で役立つことでしょう。

(more…)

05/08 スクリプトエディタ上のキャレットがある行に、ファイル名をコメントで展開

スクリプトエディタ自体も、AppleScriptからコントロールすることのできる「スクリプタブルな」アプリケーションであるため、AppleScriptによってさまざまな活用が行えます。本サイトで紹介しているように、サブルーチンを動作検証用の短いサンプルプログラムとともに保存して活用していますが……肝心のサブルーチンの先頭に「このルーチンはどのような動作を行うか」をコメントで書いておくことにしています。動作検証用コードは他のプログラムにコピーしませんが、サブルーチンと先頭のコメントは他のプログラムにまるごとコピーすることにしています。このコメントはそうした意味で必須のものなのです。

保存時に、「なるべく動作内容を把握しやすいファイル名で」保存することにしているため、そのファイル名と動作内容を記しておくコメントは……ほとんど、というよりも、「まるっきり一緒」ということになりがちです。

そこで、本スクリプトをScript Menuに入れておき、サブルーチンの先頭にカーソルを置いた状態でScript Menuから本スクリプトを実行すれば、ファイル名をそのまま選択位置にコメントで入れて、コンパイルまでしておいてくれるという仕組みです。個人的には、かなり便利に使っています。

途中「delay 0.1」でウェイトを入れているのは……ここでウェイトを入れないとうまく動作しなかったためで、まるで料理にふりかける一振りの塩のごとく、適切なウェイト命令は処理を適切に実行させる威力を発揮します。とくに、アプリケーションに対してコントロールを行うことがメインのAppleScriptにおいて、delay命令の持つ意義は大きなものになります。

sce1.jpeg

sce2.jpeg

sce3.jpeg

スクリプト名:スクリプトエディタ上のキャレットがある行に、ファイル名をコメントで展開

tell applicationScript Editor
  activate
  
tell window 1
    set a to name
    
    
set aText to” & a & return
    
set the clipboard to aText
    
  end tell
end tell

tell applicationSystem Events
  tell processScript Editor
    keystrokevusing {command down}
  end tell
end tell

delay 0.1

tell applicationScript Editor
  activate
  
tell document a
    compile
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

04/05 すべてのScriptをDockから取り出す

Script Menuに入れて使うタイプのScriptです。AppleScriptでプログラムを書き始めると、気がつけば大量のウィンドウを開いて作業をしていることがよくあります(汗) 邪魔なので途中のものをDockにしまっておいたりするわけですが、そのウィンドウをすべてDockから取り出すのは割と面倒です。で、面倒な作業をワンアクションで実行できるようにScriptを書いた次第です。

スクリプトエディタのウィンドウがDockに大量に入っている状態

スクリプト名:すべてのScriptをDockから取り出す
tell applicationScript Editor
  tell (every window whose name is not equal to “”)
    set visible to true
  end tell
  
tell windowイベントログの履歴to set visible to false
  
tell window結果の履歴to set visible to false
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に