art-standard-lib
Version:
The Standard Library for JavaScript that aught to be.
188 lines (158 loc) • 5.04 kB
text/coffeescript
Inspect = require './Inspect/namespace'
{callStack} = require './CallStack'
{isString} = require './TypesExtended'
{peek} = require './ArrayExtensions'
{merge} = require './Core'
{deepResolve, containsPromises} = require './Promise'
{isNode, getEnv} = require './Environment'
{stripAnsi} = require './Ansi'
{red, yellow} = require './TerminalColors'
{disableLog} = getEnv()
module.exports = class Log
# autodetect context from
# stack (grabed with callStack()). Ignores stack[0]
# defaultContext - what to report if context cannot be determined
@contextString: (stack, defaultContext) =>
if stack && caller = stack[1]
if caller.original
caller.original
else
context = if caller.function
if caller.class
"#{caller.class}::#{caller.function}()"
else
caller.function+"()"
else if defaultContext
defaultContext+":"
else
""
"at " + caller.sourceFileName + "-#{caller.sourceLine}: " + context if caller.sourceFileName
else
"at #{defaultContext || "(unknown context)"}"
@autoSizedIndepect: (toInspect, maxLength = 512, maxDepth = 10) =>
inspected = null
depth = maxDepth
depth-- while (inspected = Inspect.inspectLean toInspect, maxDepth:depth, maxLength:maxLength).match(/\.\.\.$/)
inspected
@loggedParamsString: (params) =>
if typeof params == "string"
params
else
@autoSizedIndepect params
@hideLogging: => @loggingHidden = true
@showLogging: => @loggingHidden = false
@rawLog: (args...)=>
console.log args... unless @loggingHidden
@rawErrorLog: (args...)=>
return if @loggingHidden
if isNode
str = args.join ' '
console.error red str
else
console.error args...
@rawWarningLog: (args...)=>
return if @loggingHidden
if isNode
str = args.join ' '
console.warn yellow str
else
console.warn args...
noOptions = {}
getLogger = ({isError, isWarning}) ->
if isError then Log.rawErrorLog
else if isWarning then Log.rawWarningLog
else Log.rawLog
promiseLogId = 1
@logCore: (m, stack, options = noOptions) =>
if @alternativeLogger
@alternativeLogger.logCore m, stack, options
if options.resolvePromises
@log.resolvePromiseWrapper m, (toLog, label) =>
@_logNow "#{label}": toLog, stack, options
else
@_logNow m, stack, options
@_logNow: (m, stack, options) =>
{className, color} = options
logger = getLogger options
if isNode
logger if isString m
if color
m
else
stripAnsi m
else
Inspect.formattedInspect m, merge {maxLineLength: process.stdout.columns}, options
else
logger m #, "\n# StandardLib.log called " + @contextString stack, className
standardOptions = if isNode
try
eval("require") "colors"
color: process.stdout.isTTY
else {}
# always returned the last argument passed in. That way you can:
# bar = foo # log foo's value in the middle of an expression, along with other values, without altering the rest of the expression
# bar = @log 1, 2, 3, foo
@log: (args...) =>
if disableLog
peek args
else
@log.withOptions standardOptions, args...
@log.full = (args...) =>
@log.withOptions
maxArrayLength: 100000
args...
# IN: logger: (toLog, label, wasResolvedOrRejected: true/false)
@log.resolvePromiseWrapper = (m, logger) ->
if containsPromises m
toResolve = m
logId = promiseLogId++
logger m, "RESOLVING_#{logId}", false
deepResolve toResolve #, (promiseResult) -> 'promise.then': promiseResult
.then (resolvedM) =>
logger resolvedM, "RESOLVED_#{logId}", true
.catch (rejected) =>
logger rejected, "REJECTED_#{logId}", true, true
else
logger m, false
@log.withOptions = (options, args...) ->
m = if args.length == 1
args[0]
else
args
Log.logCore m, callStack(), options
peek args
###
IN:
labelString, value
OR object with one or more properties (usually just one)
returns the last value of the objects last key-value pair
EX:
log.withLabel foo: myObject
# out: myObject
log.withLabel "foo", myObject
# out: myObject
###
@log.withLabel = (a, b) =>
if isString a
obj = {}
obj[a] = b
@log obj
b
else
ret = null
ret = v for k, v of a
@log obj
ret
@log.unquoted = (args...) => @log.withOptions merge(standardOptions, unquoted: true), args...
@log.labeled = @log.withLabel
@log.error = (args...) => @log.withOptions isError: true, args...
@log.warn = (args...) => @log.withOptions isWarning: true, args...
# same output as log, but returns the last value of the objects key-value pair
# logL: labeled Log
@logL: (obj) =>
console.warn "DEPRICATED: logL. USE log.labeled"
ret = null
for k, v of obj
ret = v
@log obj
ret