Automator で作業をしていると、同じような作業を繰り返していることに気がつきます。定型作業を自動化させるのが Automator の目的なのに、その Automator で同じ作業を繰り返しているなんて。どうも、腑に落ちません。
Automator は登場した当初から AppleScript に対応していました。登場した当初はどうにも重たくて、以来使っていませんでした。Leopard の Automator で「変数」が使えるようになり、「ほう」と思ったものですが、やはりほとんど使いませんでした。
Snow Leopard インストールを期に使ってみたのですが、Automator 自身を Automator で操作できるわけでもなく、Automator の自動化は AppleScript からという環境に変わりはないようです。
唯一、変わったことといえば AppleScript からは「変数」が操作できるようになっていることぐらいでしょうか。反面、新規ワークフローの作成はスムーズにできなくなっています(必ずテンプレートを選択するシートが表示されるので)。
最初にも書いたように Automator は定型作業の繰り返しです。どのワークフローもおおむね同じようなアクションと変数を使います。特に「サービス」関連のワークフローにその傾向があります。
また、デバッグ時に同じようなアクションを何度も追加したり、削除したり...という作業が少なからず発生します。これが、結構手間だったりします。そのためでしょうか、Automator には add と remove という命令が備わっています。
tell application "Automator"
if not (front workflow exists) then return
add Automator action "選択された Finder 項目を取得" to front workflow at index 1
end tell
名前参照で書いていますが、互換性を考えるなら Automator action の bundle id 属性などを使う方がいいと思います。
tell application "Automator"
if not (front workflow exists) then return
set bundle_identifier to "com.apple.Automator.Get_Selected_Finder_Items_2"
add Automator action id bundle_identifier to front workflow at index 1
end tell
ファイルやフォルダを処理するサービスなどは「選択された Finder 項目を取得」アクションを最初においてワークフローのデバッグを行うのですが、デバッグが終われば必要なくなります。remove 命令を使えば不必要なアクションや変数を取り除くことができます。
tell application "Automator"
if not (front workflow exists) then return
set bundle_identifier to "com.apple.Automator.Get_Selected_Finder_Items_2"
tell front workflow
set remove_actions to Automator actions whose bundle id is bundle_identifier
repeat with this_action in remove_actions
remove this_action
end repeat
end tell
end tell
デバッグ時には特定のアクションの使用、不使用の切り替えを行いたいときがあります。Automator action の enabled 属性で切り替えることができます。次のスクリプトでは使用されているアクションの中から選択されたものを使用停止にします。
tell application "Automator"
if not (front workflow exists) then return
tell front workflow
set action_list to a reference to (Automator actions whose enabled is true)
if (count of action_list) is 0 then return
set action_names to name of action_list
set use_actions to choose from list action_names default items (item 1 of action_names) with multiple selections allowed
if use_actions is false then return
repeat with this_action in use_actions
set enabled of Automator action this_action to false
end repeat
end tell
end tell
変数なども同じように add, remove 命令で追加や削除が行えます。次のスクリプトは変数の一覧の中から選択されたものをワークフローに追加します。
tell application "Automator"
if not (front workflow exists) then return
set variable_list to name of variables
my combSort(variable_list)
set used_variables to choose from list variable_list default items (item 1 of variable_list) with multiple selections allowed
if used_variables is false then return
repeat with this_value in used_variables
add variable this_value to front workflow
end repeat
end tell
on combSort(theList)
set gap to count theList
repeat
set gap to (gap * 10) div 13
if gap is 0 then set gap to 1
set flag to false
repeat with i from 1 to (count theList) - gap
if (item i of theList) is greater than (item (i + gap) of theList) then
set flag to true
set tmp to item i of theList
set item i of theList to item (i + gap) of theList
set item (i + gap) of theList to tmp
end if
end repeat
if not ((gap is greater than 1) or flag) then exit repeat
end repeat
end combSort
変数などは複数のワークフローで使い回したいときがあります。テンポラリなファイルの保存先などはそういったものの一つです。あるワークフローにある変数を他のワークフローにコピーする...こういうことも add 命令で可能です。次のスクリプトはワークフローの変数を他のワークフローにコピーするスクリプトです。
tell application "Automator"
activate
if (count workflows) < 2 then return
set name_list to name of workflows
set source_document to choose from list name_list default items (item 1 of name_list) with prompt "Select source workflow:"
if source_document is false then return
set source_document to source_document as text
set name_list to my remove_item(name_list, source_document)
set destination_document to choose from list name_list default items (item 1 of name_list) with prompt "Select destination workflow:"
if destination_document is false then return
set destination_document to destination_document as text
set original_variables to name of variables of workflow source_document
set used_variables to choose from list original_variables default items (item 1 of original_variables) with multiple selections allowed
if used_variables is false then return
repeat with this_value in used_variables
set contents of this_value to variable this_value of workflow source_document
end repeat
repeat with this_value in used_variables
add this_value to workflow destination_document
end repeat
end tell
on remove_item(the_list, removed_item)
set new_list to {}
repeat with this_item in the_list
set this_item to contents of this_item
if this_item is not removed_item then
set end of new_list to this_item
end if
end repeat
return new_list
end remove_item
保存されたワークフローの実態はパッケージなんですが、パッケージの中身は至ってシンプルで document.wflow というファイルがあるだけです(サービスなんかだと Info.plist も追加されるけど)。このファイルはすべての情報が書かれているプロパティリストファイルです。ファイルの中をのぞくだけで、そのワークフローがどんなアクションを利用しているかが分かります。
ダウンロードしてきたワークフローの中身を確認するのに Automator を起動する必要はなく、このファイルを見るとすべてが分かります。このことを利用して、Finder で選択されているワークフローで使われているアクションの一覧を表示するスクリプト。
set workflow_plist to ":Contents:document.wflow"
tell application "Finder"
set current_selection to selection
if selection is {} then return
set info_list to {}
repeat with this_item in current_selection
set this_item to this_item as text
set plist_file to this_item & workflow_plist
if exists (alias plist_file) then
set workflow_info to my get_action_info(POSIX path of plist_file)
if workflow_info is not {} then
set action_text to my join(workflow_info, return & tab)
set end of info_list to displayed name of alias this_item & return & tab & action_text & return
end if
end if
end repeat
end tell
if info_list is not {} then
tell application "TextEdit"
activate
set the_document to make new document
set text of the_document to my join(info_list, return)
end tell
end if
on join(the_list, delimiter)
tell (a reference to text item delimiters)
set {tid, contents} to {contents, delimiter}
set {the_text, contents} to {the_list as text, tid}
end tell
return the_text
end join
on get_action_info(workflow_file)
tell application "System Events"
set plist_file to property list file (workflow_file)
tell plist_file
set action_info_list to {}
repeat with this_item in property list items of property list item "actions"
set end of action_info_list to value of property list item "ActionName" of property list item "action" of this_item
end repeat
end tell
return action_info_list
end tell
end get_action_info
サービスをいくつか作っていると、メニューに表示される名前を変更したいときがあります。これはワークフローの名前を Finder で変更しても変わるわけではなく、変更するには Automator でワークフローを開き別名で再保存するか、ワークフローのパッケージ内にある Info.plist の値を変更する必要があります。いちいちそういうことをするのも面倒なので、作ったのが次のスクリプト。
property file_extensions : {".workflow"}
tell application "Finder"
set current_selection to selection
if current_selection is {} then return
set workflow_files to {}
repeat with this_item in current_selection
set file_name to displayed name of this_item
set this_item to POSIX path of (this_item as text)
set {file_name, ext} to my splitext(file_name)
if ext is in file_extensions then
set plist_file to this_item & "/Contents/Info.plist"
my set_defaut_menu_item_name(plist_file, file_name)
end if
end repeat
end tell
on set_defaut_menu_item_name(plist_file, document_name)
tell application "System Events"
if not (disk item plist_file exists) then return missing value
tell property list file plist_file
if not (property list item "NSServices" exists) then return missing value
tell property list item "NSServices"
if not (property list item "NSMenuItem" of property list item 1 exists) then return missing value
tell property list item "NSMenuItem" of property list item 1
set menu_text to value of property list item "default"
if menu_text is not document_name then
set value of property list item "default" to document_name
end if
return value of property list item "default"
end tell
end tell
end tell
end tell
end set_defaut_menu_item_name
on splitext(file_name)
set reversed_name to (reverse of (characters of file_name)) as text
set num to offset of "." in reversed_name
if num is 0 then
set ext to ""
else
set reversed_ext to text 1 thru num of reversed_name
set ext to (reverse of (characters of reversed_ext)) as text
set ext_num to count ext
set name_length to count file_name
set file_name to text 1 thru (name_length - ext_num) of file_name
end if
return {file_name, ext}
end splitext
Finder で選択されているワークフローのメニュー名をファイルの名称に変更します。
以上のスクリプト以外にもいくつかまとめて。
いつものことですが、ご利用はご自身の責任でお願いします。
ところで、Automator には AppleScript という変数があります。この変数は変わった変数で、AppleScript の実行結果を変数として利用することができます(「シェルスクリプト」という変数もそうだけど)。変数のレベルで AppleScript やシェルスクリプトが利用でき、かつ、アクションにも同じようなアクションがある...。ここまでくるとやりたい放題ですね。
0 件のコメント :
コメントを投稿