私は、AppleScriptのライフサイクル全体を通してオブジェクトの状態を記録しようとしています。他の言語では、オブジェクトのtoString()メソッドは同等のテキストをレンダリングし、それらを使用できます。 AppleScriptでは、これは当てはまらないようです。
convert applescript object to string (similar to toString)
Finderオブジェクト(およびそのプロパティ)をAppleScript Editorの「結果」ウィンドウに出力しますが、実行されるのは最後のステートメントの場合のみです。
Trace()ステートメント(ログ記録の目的でメッセージを受け取る)がある場合:
on trace(message)
do Shell script "cat >>~/log/applescript.txt <<END_OF_THE_LOG
" & (message as text) & "
END_OF_THE_LOG"
end trace
同じオブジェクトをログに記録しようとすると、
Can’t make properties of application "Finder" into type text.
コンソールにログを記録するより良い方法を受け入れていますが、いずれかの方法をテストするためにスクリプトの途中でオブジェクトのプロパティを記述する方法(AppleScript Editorのように)を見つけたいです。
AppleScript Editorでlog
ステートメントを使用するだけです。 Applescript Editorで結果を表示したら、ウィンドウの下部にある[イベント]ボタンを押します。通常、「結果」ボタンを押すと、言及した最後のステートメントの結果のみが表示されます。ボタンを「イベント」に変更します。これにより、スクリプトの実行中に発生しているすべての内容と、コード全体に配置したlog
ステートメントもすべて表示されます。 log
ステートメントはテキストである必要はありません。任意のオブジェクトを記録できます。
これは、スクリプトをデバッグし、何が起こっているかを確認するための最良の方法です。例として、これを試して、「イベント」を見てください。すべてがすでにログに記録されているため、イベントを表示する場合、多くのlog
ステートメントは必要ないと現実的に考えています!
set someFolder to path to desktop
log someFolder
tell application "Finder"
set someItem to first item of someFolder
log someItem
set itemProps to properties of someItem
log itemProps
end tell
AppleScriptを使用すると簡単になりません。
log
only AppleScript Editorでの実行中またはosascript
を介して(その場合はstderr
に)実行中のログ-その他の出力は失われますアプリケーションがNSAppleScript
Cocoaクラスを使用してスクリプトを実行する場合など。
log
はone引数のみを受け入れます。オブジェクト型は受け入れますが、非組み込み型の意味のある表現を簡単に取得することはできません。たとえば、_log me
_を試して、スクリプト自体に関する情報を取得します。意味のある情報を取得するには、頻繁にlog (get properties of <someObj>)
を使用する必要があります。面倒な構文に注意してください。これは、_log properties of <someObj>
_を使用するだけで、通常、それが指すプロパティの代わりに参照フォームの名前を出力するだけなので(たとえば、_log properties of me
_は無駄に出力します)ちょうど_(*properties*)
_)。
一般に、AppleScriptは非組み込み型のオブジェクトの意味のあるテキスト表現を取得することを非常に困難にします。_<someObj> as text
_(同じ:_<someObj> as string
_と同じ)breaks-throwsランタイムエラー-そのようなオブジェクトの場合; _me as text
_を試してください。
以下はこれらの問題に対処するヘルパーサブルーチンです。
dlog()
は、オブジェクトの意味のあるテキスト表現の導出と、グローバル構成変数に基づいて複数のログターゲット(syslogとファイルを含む)に書き込む機能を組み合わせたサブルーチンです。toString()
(dlog()
に効果的に埋め込まれています)は、任意のタイプの単一オブジェクトを取得し、そこから意味のあるテキスト表現を引き出すサブルーチンです。@ 1.61803への帽子の先端。彼の答えは、さまざまなロギングターゲットを実装するための指針を提供しました。
_ # Setup: Log to syslog and a file in the home dir.
# Other targets supported: "log", "alert"
# Set to {} to suppress logging.
set DLOG_TARGETS to { "syslog", "~/as.log" }
# Log properties of the front window of frontmost application.
dlog(front window of application (path to frontmost application as text))
# Log properties of own front window; note the *list* syntax for multiple args.
dlog({"my front window: ", front window})
# Get properties of the running script as string.
toString(me) # ->, e.g.: [script name="sandbox"] {selection:insertion point after character 2475 of text of document "sandbox2.scpt", frontmost:true, class:application, name:"AppleScript Editor", version:"2.6"}
_
詳細については、各サブルーチンの上のソースコードのコメントを参照してください。
_ # Logs a text representation of the specified object or objects, which may be of any type, typically for debugging.
# Works hard to find a meaningful text representation of each object.
# SYNOPSIS
# dlog(anyObjOrListOfObjects)
# USE EXAMPLES
# dlog("before") # single object
# dlog({ "front window: ", front window }) # list of objects
# SETUP
# At the top of your script, define global variable DLOG_TARGETS and set it to a *list* of targets (even if you only have 1 target).
# set DLOG_TARGETS to {} # must be a list with any combination of: "log", "syslog", "alert", <posixFilePath>
# An *empty* list means that logging should be *disabled*.
# If you specify a POSIX file path, the file will be *appended* to; variable references in the path
# are allowed, and as a courtesy the path may start with "~" to refer to your home dir.
# Caveat: while you can *remove* the variable definition to disable logging, you'll take an additional performance hit.
# SETUP EXAMPLES
# For instance, to use both AppleScript's log command *and* display a GUI alert, use:
# set DLOG_TARGETS to { "log", "alert" }
# Note:
# - Since the subroutine is still called even when DLOG_TARGETS is an empty list,
# you pay a performancy penalty for leaving dlog() calls in your code.
# - Unlike with the built-in log() method, you MUST use parentheses around the parameter.
# - To specify more than one object, pass a *list*. Note that while you could try to synthesize a single
# output string by concatenation yourself, you'd lose the benefit of this subroutine's ability to derive
# readable text representations even of objects that can't simply be converted with `as text`.
on dlog(anyObjOrListOfObjects)
global DLOG_TARGETS
try
if length of DLOG_TARGETS is 0 then return
on error
return
end try
# The following tries hard to derive a readable representation from the input object(s).
if class of anyObjOrListOfObjects is not list then set anyObjOrListOfObjects to {anyObjOrListOfObjects}
local lst, i, txt, errMsg, orgTids, oName, oId, prefix, logTarget, txtCombined, prefixTime, prefixDateTime
set lst to {}
repeat with anyObj in anyObjOrListOfObjects
set txt to ""
repeat with i from 1 to 2
try
if i is 1 then
if class of anyObj is list then
set {orgTids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {", "}} # '
set txt to ("{" & anyObj as string) & "}"
set AppleScript's text item delimiters to orgTids # '
else
set txt to anyObj as string
end if
else
set txt to properties of anyObj as string
end if
on error errMsg
# Trick for records and record-*like* objects:
# We exploit the fact that the error message contains the desired string representation of the record, so we extract it from there. This (still) works as of AS 2.3 (OS X 10.9).
try
set txt to do Shell script "egrep -o '\\{.*\\}' <<< " & quoted form of errMsg
end try
end try
if txt is not "" then exit repeat
end repeat
set prefix to ""
if class of anyObj is not in {text, integer, real, boolean, date, list, record} and anyObj is not missing value then
set prefix to "[" & class of anyObj
set oName to ""
set oId to ""
try
set oName to name of anyObj
if oName is not missing value then set prefix to prefix & " name=\"" & oName & "\""
end try
try
set oId to id of anyObj
if oId is not missing value then set prefix to prefix & " id=" & oId
end try
set prefix to prefix & "] "
set txt to prefix & txt
end if
set lst to lst & txt
end repeat
set {orgTids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {" "}} # '
set txtCombined to lst as string
set prefixTime to "[" & time string of (current date) & "] "
set prefixDateTime to "[" & short date string of (current date) & " " & text 2 thru -1 of prefixTime
set AppleScript's text item delimiters to orgTids # '
# Log the result to every target specified.
repeat with logTarget in DLOG_TARGETS
if contents of logTarget is "log" then
log prefixTime & txtCombined
else if contents of logTarget is "alert" then
display alert prefixTime & txtCombined
else if contents of logTarget is "syslog" then
do Shell script "logger -t " & quoted form of ("AS: " & (name of me)) & " " & quoted form of txtCombined
else # assumed to be a POSIX file path to *append* to.
set fpath to contents of logTarget
if fpath starts with "~/" then set fpath to "$HOME/" & text 3 thru -1 of fpath
do Shell script "printf '%s\\n' " & quoted form of (prefixDateTime & txtCombined) & " >> \"" & fpath & "\""
end if
end repeat
end dlog
_
_ # Converts the specified object - which may be of any type - into a string representation for logging/debugging.
# Tries hard to find a readable representation - sadly, simple conversion with `as text` mostly doesn't work with non-primitive types.
# An attempt is made to list the properties of non-primitive types (does not always work), and the result is prefixed with the type (class) name
# and, if present, the object's name and ID.
# EXAMPLE
# toString(path to desktop) # -> "[alias] Macintosh HD:Users:mklement:Desktop:"
# To test this subroutine and see the various representations, use the following:
# repeat with elem in {42, 3.14, "two", true, (current date), {"one", "two", "three"}, {one:1, two:"deux", three:false}, missing value, me, path to desktop, front window of application (path to frontmost application as text)}
# log my toString(contents of elem)
# end repeat
on toString(anyObj)
local i, txt, errMsg, orgTids, oName, oId, prefix
set txt to ""
repeat with i from 1 to 2
try
if i is 1 then
if class of anyObj is list then
set {orgTids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {", "}}
set txt to ("{" & anyObj as string) & "}"
set AppleScript's text item delimiters to orgTids # '
else
set txt to anyObj as string
end if
else
set txt to properties of anyObj as string
end if
on error errMsg
# Trick for records and record-*like* objects:
# We exploit the fact that the error message contains the desired string representation of the record, so we extract it from there. This (still) works as of AS 2.3 (OS X 10.9).
try
set txt to do Shell script "egrep -o '\\{.*\\}' <<< " & quoted form of errMsg
end try
end try
if txt is not "" then exit repeat
end repeat
set prefix to ""
if class of anyObj is not in {text, integer, real, boolean, date, list, record} and anyObj is not missing value then
set prefix to "[" & class of anyObj
set oName to ""
set oId to ""
try
set oName to name of anyObj
if oName is not missing value then set prefix to prefix & " name=\"" & oName & "\""
end try
try
set oId to id of anyObj
if oId is not missing value then set prefix to prefix & " id=" & oId
end try
set prefix to prefix & "] "
end if
return prefix & txt
end toString
_
次のいずれかを試してください。
# echo to file
do Shell script "echo " & quoted form of (myObj as string) & ¬
" > ~/Desktop/as_debug.txt"
# write to file
set myFile to open for access (path to desktop as text) & ¬
"as_debug2.txt" with write permission
write myObj to myFile
close access myFile
# log to syslog
do Shell script "logger -t 'AS DEBUG' " & myObj
# show dialog
display dialog "ERROR: " & myObj
ログに記録しようとしているものがテキストでない場合は、次を試してください。
quoted form of (myObj as string)
do Shell script "echo '" & (current date) & ": Found " & Thisfilename & "' >> ~/logs/MyGreatAppleScript.log"
コンソールログの例を次に示します。
set my_int to 9945
log my_int
set my_srt to "Hamza"
log my_srt
set my_array ["Apple","Mango","Banana","Gava"]
log my_array
set my_obj to {"ALi"} as string
log my_obj
toString()
...と同様.
on TextOf(aVariable)
try
return "" & aVariable
on error errm
if errm begins with "Can’t make " ¬
and errm ends with " into type Unicode text." then ¬
return text 12 through -25 of errm
return "item of class " & (class of aVariable) & return & errm
end try
end TextOf