Skip to content

Instantly share code, notes, and snippets.

@zarigani
Created February 26, 2009 00:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zarigani/70546 to your computer and use it in GitHub Desktop.
Save zarigani/70546 to your computer and use it in GitHub Desktop.
AppleScript's Library & Script
(*
GUIライブラリ
ロード方法の例(このライブラリをユーザースクリプトフォルダに"_gui.scpt"で保存した場合)
property GUI : load script file ((path to scripts folder as text) & "_gui.scpt")
あるいは動的に...
set GUI to load script file ((path to scripts folder as text) & "_gui.scpt")
開発&テスト環境
MacBook OSX 10.5.6
AppleScript 2.0.1
Script Editor 2.2.1 (100.1)
*)
--初期化処理(Quicksilverからの起動なら、ひと呼吸置いて実行する)
on init()
if is_from_quicksilver() then
delay 0.2
end if
end init
--GUIスクリプティングが無効なら、有効にすることを勧めるメッセージを出力する
on check()
tell application "System Events"
if UI elements enabled is false then
tell application "System Preferences"
activate
set current pane to pane "com.apple.preference.universalaccess"
set msg to "GUIスクリプティングが利用可能になっていません。\n\"補助装置にアクセスできるようにする\" にチェックを入れて続けますか?"
--display dialog msg buttons {"OK"} default button "OK" with icon note --giving up after 10
display dialog msg buttons {"キャンセル", "チェックを入れて続ける"} with icon note
end tell
--error "中断しました。"
set UI elements enabled to true
delay 1
tell application "System Preferences" to quit
delay 1
end if
end tell
end check
--click_menu(app_name, menu_path)
--メニュー操作をシンプルに実行する
--app_nameは、操作対象のアプリケーション名
--app_nameを""にすると、実行時にアクティブなアプリケーションに対する操作となる
--menu_pathは、テキストまたはリスト
-- click_menu("", "編集/検索/検索...") --OK
-- click_menu("Script Editor", {"編集", "検索", "検索..."}) --OK
-- click_menu("Script Editor", "編集", "検索", "検索...")--NG(リストでないので、編集をクリックする操作になってしまう)
--…または...の種類に注意
-- click_menu("Script Editor", "Apple/システム環境設定…") --全角記号1文字
-- click_menu("Script Editor", "スクリプトエディタ/環境設定...") --半角ドット3文字
--小さいカナ文字に注意(×ウィンドウ ○ウインドウ)
--アップルメニューの場合はpath_menuに"Apple"を指定する
-- click_menu("", "Apple/この Mac について")
--アイテム番号による指定も可能
--アイテム番号では区切り線も1と数える
--アイテム番号とアイテム名称の混在可能
-- click_menu("Script Editor", "スクリプトエディタ/サービス/テキストエディット/選択部分を含む新しいウインドウを開く")
-- click_menu("Script Editor", "2/5/32/2") --=="スクリプトエディタ/サービス/テキストエディット/選択部分を含む新しいウインドウを開く"
-- click_menu("", "2/環境設定...") --"スクリプトエディタ/環境設定..."
--アイコンメニューは、メニューバーのアイテム番号の選択とキー操作で行う
--アイコンメニューのapp_nameは"SystemUIServer"
--"SystemUIServer"以外のアイコンメニューを操作する方法は、現状分からない...
--例:ログインウィンドウを表示する(ログインユーザーが1人だけの場合)
(*
click_menu("SystemUIServer", "16")
shortcut("↓")
shortcut("↓")
shortcut("space")
*)
on click_menu(app_name, menu_path)
if menu_path is "" then
error "menu_path が入力されていません。"
end if
if app_name is "" then
set app_name to frontmost_app()
end if
set mp to split(menu_path, "/")
tell application "System Events"
tell process app_name
if "AppleScript Runner" is in my every_process() or ¬
frontmost is false then
set frontmost to true
end if
if mp's length = 1 then
menu bar 1's (menu bar item (my number_from(mp's item 1)))
else
--menu bar 1's menu bar item (mp's item 1)'s menu (mp's item 1)
menu bar 1's (menu bar item (my number_from(mp's item 1)))'s menu 1
repeat with i from 2 to mp's length
if i < mp's length then
--result's menu item (mp's item i)'s menu (mp's item i)
result's (menu item (my number_from(mp's item i)))'s menu 1
else
result's (menu item (my number_from(mp's item i)))
end if
end repeat
end if
click result --click:クリックする/pick:選択する--ほぼ同等だが、アイコンメニューにはclickが必須
delay 0.1 --連続してメニューを操作する時、ひと呼吸必要
end tell
end tell
end click_menu
--shortcut(app_name, key_text)
--キーボードショートカット操作をシンプルに実行する
--引数のkey_textには、ハイフンで区切った文字列、もしくはリストで指定する
-- shortcut("", "command-option-L")
-- shortcut("", {"command", "option", "L"})
--文字列やリストの最後は必ず、一般キーかキーコードにする必要あり
--一般キーとは、command, option, control, shift, fn以外のキー
--キーコードは3桁の数字で指定する
-- shortcut("", "003") --f
-- shortcut("", "3") --3
--fnキーはキー操作文字列には利用できない
--ファンクションキー等は、キーコードで指定する
-- f1:122 f2:120 f3:99 f4:118 f5:96 f6:97 f7:98 f8:100 f9:101 f10:109 f11:103 f12:111
--一般キーとして以下のキーワードを利用可能
-- delete esc ← → ↓ ↑ space tab return
--利用例:
-- shortcut("", "command-option-control-shift-A") --==keystroke "a" using {command down, option down, control down, shift down}
-- shortcut("", "command-126") --==key code 126 using {command down}
-- shortcut("", "command-1") --==keystroke "1" using {command down}
-- shortcut("Finder", "control-space")
on shortcut(app_name, key_text)
if key_text is "" or key_text is {} then
error "key_text が入力されていません。"
end if
if (count of key_text) = 1 then
set key_list to split(key_text's first item, "-")
else
set key_list to split(key_text, "-")
end if
set last_key to downcase(key_list's last item)
set modifier_key to {}
if "command" is in key_list then set modifier_key to modifier_key & command down
if "option" is in key_list then set modifier_key to modifier_key & option down
if "control" is in key_list then set modifier_key to modifier_key & control down
if "shift" is in key_list then set modifier_key to modifier_key & shift down
if last_key is "delete" then
set last_key to 51 --delete
else if last_key is "esc" then
set last_key to 53 --esc
else if last_key is "" then
set last_key to 123 --
else if last_key is "" then
set last_key to 124 --
else if last_key is "" then
set last_key to 125 --
else if last_key is "" then
set last_key to 126 --
else if last_key is "space" then
set last_key to space
else if last_key is "tab" then
set last_key to tab
else if last_key is "return" then
set last_key to return
else if last_key's length is 3 then
try
set last_key to last_key as number
end try
end if
press_key(app_name, last_key, modifier_key)
end shortcut
--キー操作を実行する
--利用例:
-- press_key("1", command down)
-- press_key(126, command down)
on press_key(app_name, normal_key, modifier_key)
--delay 0.2 --環境によって、必要なひと呼吸が変わってくる可能性がある
if app_name is "" then
set app_name to frontmost_app()
end if
tell application "System Events"
tell process app_name
if "AppleScript Runner" is in my every_process() or ¬
frontmost is false then
set frontmost to true
end if
if my is_number(normal_key) then
key code normal_key using modifier_key
else
keystroke normal_key using modifier_key
end if
--delay 0.1
end tell
end tell
end press_key
--Quicksilverから起動しているかどうか
on is_from_quicksilver()
try
my name as text
false
on error
true
end try
end is_from_quicksilver
--起動中のアプリケーション名をリストで取得する
on every_process()
tell application "System Events"
--name of every process
--every process's name
processes's name
end tell
end every_process
--最前面のアプリケーション名(拡張子なし)を取得する
on frontmost_app()
--short name of (info for (path to frontmost application)) -- short name属性がない場合、missing valueが返ってくる
--name of (path to frontmost application) --拡張子が付属してしまう。"Script Editor.app"
tell application "System Events"
set name_list to processes's name whose frontmost is true
name_list's first item
end tell
end frontmost_app
--1番上の書類ウィンドウを取得する(1番上の書類ウィンドウが存在しない場合、書類ウィンドウに限らず一番上のウィンドウを取得する)
on front_window()
tell application "System Events"
tell process (my frontmost_app())
try
set topWindow to item 1 of (every window whose subrole is "AXStandardWindow") --1番上の書類ウィンドウ
topWindow --1番上の書類ウィンドウが存在しない場合、以下のエラー処理になる。
on error
front window --set topWindow to front window --window 1
end try
end tell
end tell
end front_window
--このライブラリが依存する_lib.scptのコピー
on do_ruby_script(ruby_code)
set shell_code to "ruby -e \"puts(" & ruby_code & ")\""
do shell script shell_code
end do_ruby_script
on downcase(str)
do_ruby_script("'" & str & "'.downcase")
end downcase
on split(sourceText, separator)
if sourceText = "" then return {}
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to {separator}
set theList to text items of sourceText
set AppleScript's text item delimiters to oldDelimiters
return theList
end split
on is_number(num)
num's class is integer or num's class is real
end is_number
on is_number_text(str)
try
str as number
true
on error
false
end try
end is_number_text
on number_from(str)
try
str as number
on error
str
end try
end number_from
(*
on click_menu(app_name, menu_path)
set mp to split(menu_path, "/")
tell application "System Events"
tell process app_name
set frontmost to true --必ず、アクティブにしておく
tell menu bar 1
tell menu bar item (mp's item 1)
tell menu (mp's item 1)
if mp's length is 2 then
pick ¬
menu item (mp's item 2)
else if mp's length is 3 then
pick ¬
menu item (mp's item 2)'s ¬
menu (mp's item 2)'s ¬
menu item (mp's item 3)
(*
tell menu item (mp's item 2)
tell menu (mp's item 2)
pick menu item (mp's item 3)
end tell
end tell
*)
else if mp's length is 4 then
pick ¬
menu item (mp's item 2)'s ¬
menu (mp's item 2)'s ¬
menu item (mp's item 3)'s ¬
menu (mp's item 3)'s ¬
menu item (mp's item 4)
(*
tell menu item (mp's item 2)
tell menu (mp's item 2)
tell menu item (mp's item 3)
tell menu (mp's item 3)
pick menu item (mp's item 4)
end tell
end tell
end tell
end tell
*)
else
error "メニューパス \"" & menu_path & "\" を認識できません。"
end if
end tell
end tell
end tell
delay 0.1 --連続してメニューを操作する時、ひと呼吸必要
end tell
end tell
end click_menu
*)
(*
on click_menu2(app_name, menu_name1, menu_name2)
tell application "System Events"
tell process app_name
set frontmost to true --必ず、アクティブにしておく
tell menu bar 1
tell menu bar item menu_name1
tell menu menu_name1
pick menu item menu_name2
end tell
end tell
end tell
delay 0.1 --連続してメニューを操作する時、ひと呼吸必要
end tell
end tell
end click_menu2
on click_menu3(app_name, menu_name1, menu_name2, menu_name3)
tell application "System Events"
tell process app_name
set frontmost to true --必ず、アクティブにしておく
tell menu bar 1
tell menu bar item menu_name1
tell menu menu_name1
tell menu item menu_name2
tell menu menu_name2
pick menu item menu_name3
end tell
end tell
end tell
end tell
end tell
delay 0.1 --連続してメニューを操作する時、ひと呼吸必要
end tell
end tell
end click_menu3
*)
(*
LIBライブラリ
ロード方法の例(このライブラリをユーザースクリプトフォルダに"_lib.scpt"で保存した場合)
property LIB : load script file ((path to scripts folder as text) & "_lib.scpt")
あるいは動的に...
set LIB to load script file ((path to scripts folder as text) & "_lib.scpt")
開発&テスト環境
MacBook OSX 10.5.6
AppleScript 2.0.1
Script Editor 2.2.1 (100.1)
*)
--rubyコードを実行して結果を返す
--do_ruby_script({"require 'uri'", "URI.escape(%q|" & "tell application \"System Events\" --ショートカット操作をする限り" & "|)"})
on do_ruby_script(ruby_code)
set ruby_code to ruby_code as list
set last_code to ruby_code's last item
if (count of ruby_code) 2 then
set pre_code to join(ruby_code's items 1 thru -2, ";") & ";"
else
set pre_code to ""
end if
set shell_code to "ruby -e \"" & pre_code & "puts(" & last_code & ")\""
log shell_code
do shell script shell_code
end do_ruby_script
--URIエンコードして結果を返す
--uri_escape("set lib to load script file ((path to scripts folder as text) & \"_lib.scpt\")")
--uri_escape(the clipboard)
on uri_escape(str)
str
replace(result, "\"", "__DQT__")
replace(result, "\\", "__BSL__")
replace(result, "__DQT__", "\\\"")
--log result
do_ruby_script({"require 'uri'", "URI.escape(%q|" & result & "|)"})
replace(result, "__BSL__", "%5C")
end uri_escape
--正規表現の比較をして真偽値を返す
--re("/\\d/", "abc1")
--re("/^[\\+\\-]?[\\d\\.\\,]+$/", "+123,456.789")
on reg(reg_text, str)
try
do_ruby_script(reg_text & " =~ '" & str & "'") as integer
true
on error
false
end try
end reg
--数値を3桁区切りのテキストにする
on number_with_delimiter(num)
--注意:バックスラッシュは、バックスラッシュでエスケープすること(\\)。AppleScriptでは特殊な文字として扱われるため。
--(num.to_s =~ /[-+]?¥d{4,}/) ? (num.to_s.reverse.gsub(/¥G((?:¥d+¥.)?¥d{3})(?=¥d)/, '¥1,').reverse) : num.to_s
--(num.to_s =~ /[-+]?\\d{4,}/) ? (num.to_s.reverse.gsub(/\\G((?:\\d+\\.)?\\d{3})(?=\\d)/, '\\1,').reverse) : num.to_s
do_ruby_script("('" & num & "' =~ /[-+]?\\d{4,}/) ? ('" & num & "'.reverse.gsub(/\\G((?:\\d+\\.)?\\d{3})(?=\\d)/, '\\1,').reverse) : '" & num & "'")
end number_with_delimiter
--printfコマンド
--printf("%3d:", 1)
--" 1:"
on printf(format, value)
do shell script "printf" & space & format & space & value
end printf
--金額の書式を整える
--number_to_currency(金額, 小数点以下の桁数, 先頭文字, 末尾文字)
--lib's number_to_currency(1000.5, 2, "¥", "円")
--"¥1,000.50円"
--on number_to_currency(num, decimal_place, header, footer)
on number_to_currency(num, decimal_place)
--do shell script "printf" & space & "%" & "." & decimal_place & "f" & space & num
printf("%" & "." & decimal_place & "f", num)
number_with_delimiter(result)
--header & result & footer
end number_to_currency
(*
on number_to_currency(arg)
do shell script "printf" & space & "%" & "." & arg's decimal_place & "f" & space & arg's num
number_with_delimiter(result)
arg's header & result & arg's footer
end number_to_currency
*)
--xが何者であるか判定する
(*
x's class is integer
x's class is real
x's class is text
x's class is list
x's class is record
*)
--数値かどうか真偽値を返す
--is_number("1")
on is_number(num)
num's class is integer or num's class is real
(*
if num = {} or num = "" then
false
else
(count of num) is 0
end if
*)
end is_number
--数字(数値に変換できるテキスト)かどうか真偽値を返す
on is_number_text(str)
try
str as number
true
on error
false
end try
end is_number_text
--テキストを数値に変換する
--数値に変換できない場合は、そのままテキストを返す
on number_from(str)
try
str as number
on error
str
end try
end number_from
--10進数値と桁数を指定して、16進数文字列を返す
--利用例:
--hex_from(123, 2)
-- "7B"
on hex_from(num, digit)
set a_list to {}
repeat while num > 0
set a_list to a_list & num mod 16
set num to num div 16
end repeat
repeat digit - (count a_list) times
set a_list to a_list & 0
end repeat
""
repeat with hex in a_list's reverse
result & "0123456789ABCDEF"'s item (hex + 1)
end repeat
end hex_from
--二重のリストに補正する
--本来、リストの中にリストを指定する想定なのだが...
-- {{"class","AppleScript"}, {"style","color:rgb(0,0,0);"}}
--リスト一つだけでは以下のように書いてしまいがち
-- {"class","AppleScript"}
--そのような状況で、本来の二重リストに修正する
-- {{"class","AppleScript"}}
on double_list_from(aList)
if aList's item 1's class is list then
aList
else
{aList}
end if
end double_list_from
--文字を繰り返し、連結して返す
--t_repeat(文字, 繰り返し回数)
--t_repeat("*", 3) as text
on t_repeat(str, aCount)
set t to ""
repeat aCount times
set t to t & str
end repeat
t
end t_repeat
--文字列を中央寄せ
--t_center(文字列, 文字列幅, 埋める文字)
--t_center("123", 6, "*")
on t_center(str, width, padding)
set len to str's length
set len_L to round_down((width - len) / 2, 0) --端数は切り捨て
set len_R to width - len_L - len
t_repeat(padding, len_L) & str & t_repeat(padding, len_R)
end t_center
--文字列を左寄せ
--t_left(文字列, 文字列幅, 埋める文字)
--t_left("123", 4, " ")
on t_left(str, width, padding)
--(str & t_repeat(padding, width))'s text 1 thru width
set str to str as text
str & t_repeat(padding, width - (count str))
end t_left
--文字列を右寄せ
--t_right(文字列, 文字列幅, 埋める文字)
--t_right("123", 4, " ")
on t_right(str, width, padding)
--(t_repeat(padding, width) & str)'s text -1 thru -width
set str to str as text
t_repeat(padding, width - (count str)) & str
end t_right
--sourceTextをseparatorでリストに変換する
--split("1,2,3,4", ",")
-- 結果:{"1", "2", "3", "4"}
on split(sourceText, separator)
if sourceText = "" then return {}
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to {separator}
set theList to text items of sourceText
set AppleScript's text item delimiters to oldDelimiters
return theList
end split
--sourceListをseparatorで区切ったテキストに変換する
--join({"1", "2", "3", "4"}, ",")
-- 結果:"1,2,3,4"
--join({{1, 2}, {3, 4}}, ",")
-- 結果:"1,2,3,4"
on join(sourceList, separator)
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to {separator}
set theText to sourceList as text
set AppleScript's text item delimiters to oldDelimiters
return theText
end join
--sourceText中の全てのtext1をtext2に置き換える
--replace("abcdefg", "bc", "_bc_")
-- 結果:"a_bc_defg"
on replace(sourceText, text1, text2)
join(split(sourceText, text1), text2)
end replace
--sourceText中の全てのlist1をlist2に置き換える
--every_replace("abcdefg", {"bc", "e", "g"}, {"_bc_", "_e_", "_g_"})
-- 結果:"a_bc_d_e_f_g_"
on every_replace(sourceText, list1, list2)
repeat with i from 1 to list1's number
set sourceText to replace(sourceText, list1's item i, list2's item i)
end repeat
end every_replace
--sourceText中の最初のtext1をtext2に置き換える
--replace_first("--tell application \"APP_NAME\" to activate--必要に応じて、アプリケーション\"APP_NAME\"をアクティブにする", "--", "--<span>")
--replace_first("end tell", "--", "--<span>")
on replace_first(sourceText, text1, text2)
set aList to split(sourceText, text1)
if (count aList) < 2 then
return sourceText
end if
set topText to join(aList's items 1 thru 2, text2)
if (count aList) = 2 then
topText
else
join({topText} & aList's items 3 thru -1, text1)
end if
end replace_first
--大文字に変換
on upcase(aText)
do_ruby_script("'" & aText & "'.upcase")
end upcase
--小文字に変換
on downcase(aText)
do_ruby_script("'" & aText & "'.downcase")
end downcase
--四捨五入する、丸め位置指定可能
--round_mid(数値, 丸め位置)
--小数位置は10の指数で指定する
-- −2: 10^-2...小数第2位まで求める
-- 3: 10^3...千の位まで求める
on round_mid(num, place)
if place 0 then
set p to 10 ^ place as integer
else
set p to 10 ^ place
end if
(round num / p rounding as taught in school) * p
end round_mid
--切り上げする、丸め位置指定可能
--round_up(数値, 丸め位置)
on round_up(num, place)
if place 0 then
set p to 10 ^ place as integer
else
set p to 10 ^ place
end if
(round num / p rounding up) * p
end round_up
--切り捨てする、丸め位置指定可能
--round_down(数値, 丸め位置)
on round_down(num, place)
if place 0 then
set p to 10 ^ place as integer
else
set p to 10 ^ place
end if
(round num / p rounding down) * p
end round_down
(*速い
set a_time to current date
repeat 100000 times--10万回で5秒
offset_in({"ab", "cde", 1, 108, {}}, {})
end repeat
(current date) - a_time--5
*)
--offset_in({"ab", "cde", 1, 108, {}}, 108)
on offset_in(src_list, find_item)
set i to 0
repeat with a_item in src_list
set i to i + 1
if a_item as list is find_item as list then return i
end repeat
0
end offset_in
(*遅い
set a_time to current date
repeat 10000 times--1万回で5秒
offset_in2({"ab", "cde", 1, 108, {}}, {})
end repeat
(current date) - a_time --5
*)
--offset_in2({"ab", "cde", 1, 108, {}}, 108)
on offset_in2(src_list, find_item)
set delimiter to "__,__"
set src_text to "__" & join(src_list, delimiter) & "__"
set find_item to "__" & find_item & "__"
set i to offset of find_item in src_text
(src_text's items 1 thru i as text) & "_"
count split(result, delimiter)
end offset_in2
--max({3, 2, 5, 1, 4})
on max(a_list)
a_list's item 1
repeat with a_item in a_list
if a_item > result then
a_item
else
result
end if
end repeat
result's contents
end max
--max_offset({3, 2, 5, 1, 4})
on offset_of_max(a_list)
set max_i to 1
repeat with i from 1 to a_list's number
if a_list's item i > a_list's item max_i then
set max_i to i
end if
end repeat
max_i
end offset_of_max
--min({3, 2, 5, 1, 4})
on min(a_list)
a_list's item 1
repeat with a_item in a_list
if a_item < result then
a_item
else
result
end if
end repeat
result's contents
end min
--min_offset({3, 2, 5, 1, 4})
on offset_of_min(a_list)
set min_i to 1
repeat with i from 1 to a_list's number
if a_list's item i < a_list's item min_i then
set min_i to i
end if
end repeat
min_i
end offset_of_min
(*
RTFクラス
アプリケーション名と書類の名前あるいは番号を指定して、RTF情報にアクセスする
アプリケーション名が""の場合は、その時アクティブなアプリケーションになる
書類の名前が""の場合は、document 1(最前面のウィンドウの書類)になる
利用例:
set RTF_OBJ to new("", "")
RTF_OBJ's everyText
RTF_OBJ's everyFont
RTF_OBJ's everySize
RTF_OBJ's everyColor
開発&テスト環境
MacBook OSX 10.5.6
AppleScript 2.0.1
Script Editor 2.2.1 (100.1)
*)
--インスタンスを生成する(コンストラクタ)
on new(app_name, doc_name_or_num)
if app_name = "" then set app_name to frontmost_app()
if doc_name_or_num = "" then set doc_name_or_num to 1
script RTF_instance
property parent : me
--global everyText, everyFont, everySize, everyColor
property everyText : missing value
property everyFont : missing value
property everySize : missing value
property everyColor : missing value
--初期化
on initalize()
--validate(検証)の順序大事
validate_presence_of_document()
parse()
validate_rtf()
validate_presence_of_text()
me
end initalize
--リッチテキスト情報を取得する(都度、メソッド呼び出しで処理すると、とっても遅くなったので、変数に代入することに)
on parse()
try
tell application app_name
tell document doc_name_or_num's paragraph
set everyText to (every attribute run)
set everyFont to (every attribute run)'s font
set everySize to (every attribute run)'s size
set everyColor to (every attribute run)'s color
end tell
end tell
end try
end parse
--documentの存在を検証
on validate_presence_of_document()
tell application app_name
try
if (count document) > 0 then return
end try
"ドキュメントがありません。"
--display dialog result buttons "OK" default button "OK" giving up after 10
display alert result giving up after 10
error
end tell
end validate_presence_of_document
--テキストの存在を検証
on validate_presence_of_text()
tell application app_name
try
if everyText's number > 0 then return
end try
"変換するテキストがありません。"
--display dialog result buttons "OK" default button "OK" giving up after 10
display alert result giving up after 10
error
end tell
end validate_presence_of_text
--変換できるリッチテキストかどうか検証
on validate_rtf()
tell application app_name
try
if everyText's number = everyFont's number and ¬
everyText's number = everySize's number and ¬
everyText's number = everyColor's number then return
end try
"リッチテキストでないため変換できません。"
--display dialog result buttons "OK" default button "OK" giving up after 10
display alert result giving up after 10
error
end tell
end validate_rtf
end script
result's initalize()
end new
--最前面のアプリケーション名(拡張子なし)を取得する
on frontmost_app()
--short name of (info for (path to frontmost application)) -- short name属性がない場合、missing valueが返ってくる
--name of (path to frontmost application) --拡張子が付属してしまう。"Script Editor.app"
tell application "System Events"
set name_list to processes's name whose frontmost is true
name_list's first item
end tell
end frontmost_app
(*
通貨両替機(サンプルコード)
関連日記:
AppleScriptで通貨両替計算機を作ってみる
http://d.hatena.ne.jp/zariganitosh/20090212/1234442419
オブジェクト指向AppleScript言語
http://d.hatena.ne.jp/zariganitosh/20090210/1234233639
*)
property LIB : load script file ((path to scripts folder as text) & "_lib.scpt")
property kind_list : {"米ドル", "ユーロ", "英ポンド", "スイスフラン"}
(*
init()
input_rate()
repeat
exchange()
end repeat
*)
init()
repeat
input_rate()
repeat
try --キャンセル ボタンを捕まえるため
exchange()
on error msg number num from obj partial result try_obj to class_name
--display dialog msg & space & num
if num is 128 then --キャンセルならループを抜ける
exit repeat
else --キャンセル以外はそのままエラー
error msg number num from obj partial result try_obj to class_name
end if
end try
end repeat
end repeat
--必要なだけ両替機を生成する
on init()
if my exchanger's all() is {} then
repeat with aKind in kind_list
my exchanger's new(aKind)
end repeat
end if
end init
--変換レートを入力する
on input_rate()
repeat with aExchanger in my exchanger's all()
set msg to "交換レート: 1" & aExchanger's currency & "は 何円?"
display dialog msg default answer aExchanger's rate
aExchanger's set_rate(text returned of result)
end repeat
end input_rate
--両替の計算をする
on exchange()
display dialog "金額を入力してください。" default answer "" buttons {"キャンセル", "外貨→円", "円→外貨"}
if button returned of result is "外貨→円" then
display dialog my exchanger's all_yen_from(text returned of result) as text
else if button returned of result is "円→外貨" then
display dialog my exchanger's all_other_from(text returned of result) as text
end if
end exchange
--通貨両替機クラス(Exchangerクラスは、_Exchangerインスタンスを生成・管理する能力を持っている)
--このクラスにnewを送信すると、ある外貨の両替に対応した両替機が一つ生成される。
--生成された両替機は、プロパティitem_listに追加され、このクラスでまとめて管理される。
script exchanger
property item_list : {}
on new(aCurrency)
set aItem to _new(aCurrency)
set item_list to item_list & aItem
aItem
end new
on _new(aCurrency)
script _Exchanger
property currency : aCurrency
property rate : 0
on set_currency(amounts)
set currency to amounts
end set_currency
on set_rate(theRate)
set rate to theRate
end set_rate
--外貨から円に変換する
on yen_from(other)
--表示例:"1,000米ドル → 100,000.99円"
my LIB's number_to_currency(other, 0) & my LIB's t_left(currency, 6, " ") & "" & my LIB's number_to_currency(other * rate, 2) & "" & return
--other & currency & " → " & (other * rate) & "円" & return
end yen_from
--円から外貨に変換する
on other_from(yen)
--表示例:"100,000円 → 1,000.99米ドル"
my LIB's number_to_currency(yen, 0) & "" & "" & my LIB's number_to_currency(yen / rate as text, 2) & currency & return
--yen & "円" & " → " & (yen / rate) & currency & return
end other_from
end script
end _new
on all()
item_list
end all
on all_yen_from(other)
set msg_list to {}
repeat with aItem in item_list
set msg_list to msg_list & aItem's yen_from(other)
end repeat
msg_list
end all_yen_from
on all_other_from(yen)
set msg_list to {}
repeat with aItem in item_list
set msg_list to msg_list & aItem's other_from(yen)
end repeat
msg_list
end all_other_from
end script
(*
メール送信後にテキストエンコーディングを自動に設定して文字化け対策
フォルダアクションから利用する
関連日記:
GUIスクリプティングなAppleScript環境を快適にする
http://d.hatena.ne.jp/zariganitosh/20090218/1235018953
*)
property GUI : load script file ((path to scripts folder as text) & "_gui.scpt")
on adding folder items to this_folder after receiving added_items
tell application "Finder" to open added_items
GUI's init()
GUI's check()
GUI's shortcut("Mail", "command-option-1")
GUI's shortcut("", "command-W")
GUI's click_menu("", "ウインドウ/メッセージビューア")
GUI's shortcut("", "command-W")
GUI's shortcut("", "command-option-N")
end adding folder items to
(*
リッチテキストをシンタックスハイライトなHTMLに変換する
関連日記:
シンタックスハイライトなHTMLに変換するオブジェクト指向AppleScript その1
http://d.hatena.ne.jp/zariganitosh/20090222/1235458945
シンタックスハイライトなHTMLに変換するオブジェクト指向AppleScript その2
http://d.hatena.ne.jp/zariganitosh/20090223/1235459255
シンタックスハイライトなHTMLに変換するオブジェクト指向AppleScript その3
http://d.hatena.ne.jp/zariganitosh/20090224/1235460563
シンタックスハイライトなHTMLに変換するオブジェクト指向AppleScript その4
http://d.hatena.ne.jp/zariganitosh/20090225/1235510758
*)
property LIB : load script file ((path to scripts folder as text) & "_lib.scpt")
property RTF : load script file ((path to scripts folder as text) & "_rtf.scpt")
property FIND_TEXTS : {"\t", "&", "<", ">", "¬"} --"\t" = tab
property PUTS_TEXTS : {" ", "&amp;", "&lt;", "&gt;", "&not;"}
property defaultFontFamily : "CourierNewPSMT"
property defaultFontSize : "12px"
property defaultColor : missing value
set RTF_OBJ to RTF's new("", "")
set defaultColor to most_hex_color(RTF_OBJ's everyText, RTF_OBJ's everyColor)
--set line_num_format to "%" & (count (RTF_OBJ's everyText's number as text)) & "d:"
set html to ""
repeat with i from 1 to RTF_OBJ's everyText's number
set line_text to RTF_OBJ's everyText's item i
set line_font to RTF_OBJ's everyFont's item i
set line_size to RTF_OBJ's everySize's item i
set line_color to RTF_OBJ's everyColor's item i
set html to html & space
--set html to html & LIB's printf(line_num_format, i) & space
repeat with j from 1 to line_text's number
set aText to line_text's item j
set aFont to line_font's item j
set aSize to line_size's item j
set aColor to line_color's item j
set html to html & text_or_tag(aText, aFont, aSize, aColor)
end repeat
end repeat
set the clipboard to tag("pre" & return, html, {"style", default_css()})
(*
htmlに変換するハンドラ
*)
--見えない文字はそのまま、見える文字はタグで囲って返す
on text_or_tag(aText, aFont, aSize, aColor)
--if reg("/^[\\t\\s\\r]+$/", originalText) then--処理が遅過ぎ
if is_invisible(aText) then
content_text(aText)
else
tag(tag_by_font(aFont), content_text(aText), {"style", css(aFont, aSize, aColor)})
end if
end text_or_tag
--見えない文字の連続かどうか真偽値で返す(見えない:true)
on is_invisible(str)
str's item 1 & LIB's replace(str, str's item 1, "")
result is in {tab, space, return}
end is_invisible
--タグで囲って返す
--利用例:
-- tag("span", "ABC", {{"class","AppleScript"}, {"style","color:rgb(0,0,0);"}})
-- <span class="AppleScript" style="color:rgb(0,0,0);">ABC</span>
--ペアリストが一つだけの場合は下記でもOK
--利用例:
-- tag("span", "ABC", {"style","color:rgb(0,0,0);"})
-- <span style="color:rgb(0,0,0);">ABC</span>
-- tag("pre", "ABC", "")
-- <pre>ABC</pre>
-- tag("pre"&return, "ABC", "")
-- <pre>
-- ABC
-- </pre>
--
on tag(tag_name, str, attr_pair_list)
if tag_name's item -1 is in {return, "\n"} then
return tag(tag_name's items 1 thru -2 as text, return & str & return, attr_pair_list) & return
end if
attr_text(double_list_from(attr_pair_list))
if result "" then
"<" & tag_name & result & ">" & str & "</" & tag_name & ">"
else if tag_name is not in {"span"} then
"<" & tag_name & ">" & str & "</" & tag_name & ">"
else
str
end if
end tag
--二重のリストに補正する
--本来、リストの中にリストを指定する想定なのだが...
-- {{"class","AppleScript"}, {"style","color:rgb(0,0,0);"}}
--リスト一つだけでは以下のように書いてしまいがち
-- {"class","AppleScript"}
--そのような状況で、本来の二重リストに修正する
-- {{"class","AppleScript"}}
on double_list_from(aList)
if aList's item 1's class is list then
aList
else
{aList}
end if
end double_list_from
--ペアリストから属性を指定するテキストを返す
--ペアリストとは{キー,値}のリストから構成されるリストを想定している
--{{"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}
--利用例:
-- attr_text({{"class","AppleScript"}, {"style","color:rgb(0,0,0);"}})
-- " class=\"AppleScript\" style=\"color:rgb(0,0,0);\""
on attr_text(pair_list)
set aText to ""
repeat with pair in pair_list
if pair's item 2 "" then
set aText to aText & space & pair's item 1 & "=\"" & pair's item 2 & "\""
end if
end repeat
aText
end attr_text
--必要な置き換えをしたテキストを返す
on content_text(str)
LIB's every_replace(str, FIND_TEXTS, PUTS_TEXTS)
end content_text
--デフォルトのインラインスタイルを返す
on default_css()
"color:" & defaultColor & ";" & "font-size:" & defaultFontSize & ";" & "font-family:" & defaultFontFamily & ";"
end default_css
--インラインスタイルを返す
on css(aFont, aSize, aColor)
--css_color(aColor) & css_font_size(aSize) & css_font_weight(aFont)
--css_color(aColor) & css_font_size(aSize) & css_font_family(aFont)
css_color(aColor) -- & css_font_weight(aFont)
end css
--フォントの色の設定コードを返す color:rgb(255,255,255);
on css_color(aColor)
hex_color(aColor)
if result = defaultColor then
return ""
else
"color:" & result -- & ";"
end if
end css_color
--フォントサイズの設定コードを返す font-size:12px;
on css_font_size(aSize)
aSize & "px"
if result = defaultFontSize then
return ""
else
"font-size:" & result & ";"
end if
end css_font_size
--フォントの太さの設定コードを返す font-weight:bold;
on css_font_weight(aFont)
if "bold" is in aFont then
"font-weight:bold;"
end if
end css_font_weight
--フォントの種類の設定コードを返す font-family:Osaka
on css_font_family(aFont)
aFont
if result = defaultFontFamily then
return ""
else
"font-family:" & result & ";"
end if
end css_font_family
--フォントに応じたタグを返す
on tag_by_font(aFont)
if "bold" is in aFont then
"b"
else
"span"
end if
end tag_by_font
--RGB指定のカラー文字列を返す
--利用例:
--rgb_color({65535, 65535, 65535})
-- 結果:"rgb(255,255,255)"
on rgb_color(color_list)
set R to (color_list's item 1) div 256
set G to (color_list's item 2) div 256
set B to (color_list's item 3) div 256
"rgb(" & R & "," & G & "," & B & ")"
end rgb_color
--16進数のカラー文字列を返す
--利用例:
--hex_color({65535, 65535, 65535})
-- 結果:"#FFFFFF"
on hex_color(color_list)
""
repeat with i in color_list
--result & LIB's hex_from(i div 256, 2)
result & LIB's hex_from(i div 4096, 1)
end repeat
"#" & result
end hex_color
--一番多く出現する16進数カラーを返す
on most_hex_color(every_text, every_color)
sum_every_color(every_text, every_color)
hex_color(result's item 1's item (LIB's offset_of_max(result's item 2)))
end most_hex_color
--カラー値を集計して、カラーと出現回数のリストで返す(見えない文字のカラーは集計しない)
--返されるリストの例:
-- {
-- {{65535, 52428, 26214}, {46003, 46003, 46003}, {10530, 0, 65535}, {16383, 32767, 0}, {0, 0, 65535}, {0, 0, 0}},
-- {404, 59, 203, 238, 72, 79}
-- }
on sum_every_color(every_text, every_color)
set sum_colors to {}
set sum_counts to {}
repeat with i from 1 to every_text's number
set line_text to every_text's item i
set line_color to every_color's item i
repeat with j from 1 to line_text's number
set a_text to line_text's item j
set a_color to line_color's item j
if is_invisible(a_text) is false then
set colors_i to LIB's offset_in(sum_colors, a_color)
if colors_i = 0 then
set sum_colors to sum_colors & {a_color}
set sum_counts to sum_counts & 1
else
set sum_counts's item colors_i to (sum_counts's item colors_i) + 1
end if
end if
end repeat
end repeat
{sum_colors, sum_counts}
end sum_every_color
(*
選択中のテキストでスポットライト検索する
Quicksilver等でショートカットを割り当てて利用する
関連日記:
GUIスクリプティングなAppleScript環境を快適にする
http://d.hatena.ne.jp/zariganitosh/20090218/1235018953
*)
property GUI : load script file ((path to scripts folder as text) & "_gui.scpt")
GUI's init()
GUI's shortcut("", "command-c")
GUI's shortcut("", "control-space")
GUI's shortcut("", "command-V")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment