AppleScript では簡単ではありません。
log
AppleScript Editor で実行中、または経由で実行中osascript
(その場合は to ) にのみログを記録します。アプリケーションがCocoa クラスstderr
を使用してスクリプトを実行する場合など、他の場合には出力が失われます。NSAppleScript
log
1 つの引数のみを受け入れます。任意のオブジェクト型を受け入れますが、非組み込み型の意味のある表現を取得するのは簡単ではありませんlog me
。たとえば、スクリプト自体に関する情報を取得してみてください。多くの場合、log (get properties of <someObj>)
意味のある情報を得るために使用する必要があります。煩雑な構文が必要であることに注意してください。これは、log properties of <someObj>
通常、単にusing を使用すると、それが指すプロパティの代わりに参照形式の名前をlog properties of me
出力するだけだからです (たとえば、無駄にただ を出力します(*properties*)
)。
<someObj> as text
一般に、<someObj> as string
AppleScriptは非組み込み型のオブジェクトの意味のあるテキスト表現を取得することを非常に困難にします。試してみてください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"}
詳細については、各サブルーチンの上のソース コード コメントを参照してください。
dlog() ソースコード
# 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
toString() ソースコード
# 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