#lang scheme/base
(require scheme/contract
(except-in srfi/1/list any)
srfi/13/string
srfi/19/time
srfi/26/cut
(planet schematics/macro/aif)
(file "base.ss")
(file "parameter.ss")
(file "time.ss"))
(define-struct log-stream (name) #:transparent)
(define make-log make-log-stream)
(define message-log (make-log 'M))
(define warning-log (make-log 'W))
(define error-log (make-log 'E))
(define-parameter current-log-preamble
(lambda () null)
(lambda (val)
(if (procedure? val)
val
(raise-exn exn:fail:contract
(format "Expected (symbol -> (listof string)), received ~a." val))))
with-log-preamble)
(define-parameter current-log-port
current-output-port
(make-guard (lambda (x)
(or (output-port? x)
(procedure? x)))
"(U output-port (-> output-port))")
with-log-port)
(define log-message
(lambda args
(log-generic message-log args)))
(define log-warning
(lambda args
(log-generic warning-log args)))
(define log-error
(lambda args
(log-generic error-log args)))
(define (log-generic log-stream message-components)
(let* ([time (current-time time-tai)]
[items (cons (log-stream-name log-stream)
(append ((current-log-preamble)) message-components))]
[out (current-log-port-ref)])
(display (string-join (map (cut format "~s" <>) items) ",") out)
(newline out)
time))
(define (current-log-port-ref)
(define port+thunk (current-log-port))
(if (output-port? port+thunk)
port+thunk
(port+thunk)))
(provide with-log-preamble
with-log-port)
(provide/contract
[struct log-stream ([name symbol?])]
[make-log (-> symbol? log-stream?)]
[message-log log-stream?]
[warning-log log-stream?]
[error-log log-stream?]
[current-log-preamble (parameter/c procedure?)]
[current-log-port (parameter/c (or/c output-port? (-> output-port?)))]
[log-message (->* () () #:rest any/c time-tai?)]
[log-warning (->* () () #:rest any/c time-tai?)]
[log-error (->* () () #:rest any/c time-tai?)]
[log-generic (-> log-stream? list? time-tai?)])