indent multi-line details, export more helpers

This commit is contained in:
Ryan Culpepper 2013-08-01 13:51:49 -04:00
parent 839323ff7c
commit e0f3876e8c
2 changed files with 51 additions and 13 deletions

View File

@ -96,4 +96,17 @@ the Racket @tech[#:doc '(lib
"scribblings/reference/reference.scrbl")]{error message convention}. "scribblings/reference/reference.scrbl")]{error message convention}.
} }
@defproc[(compose-error-detail
[field string?]
[options (listof (or/c 'value 'multi 'maybe))]
[value any/c])
string?]{
Formats a single detail for an error message. The @racket[options]
behave as described in @racket[error*].
The resulting string begins with a newline unless it is empty, so it
can be appended to the end of a base error message.
}
@(close-eval the-eval) @(close-eval the-eval)

View File

@ -1,5 +1,7 @@
#lang racket/base #lang racket/base
(require racket/contract/base (require racket/contract/base
racket/string
racket/list
syntax/srcloc syntax/srcloc
syntax/stx) syntax/stx)
@ -42,6 +44,9 @@ TODO
(->* [(or/c symbol? #f) string?] (->* [(or/c symbol? #f) string?]
[#:continued (or/c string? (listof string))] [#:continued (or/c string? (listof string))]
#:rest details-list/c #:rest details-list/c
string?)]
[compose-error-detail
(-> string? (listof field-option/c) any/c
string?)]) string?)])
;; ---- ;; ----
@ -79,11 +84,14 @@ TODO
(if (error-print-source-location) (if (error-print-source-location)
(string-append (source-location->prefix source-stx) message) (string-append (source-location->prefix source-stx) message)
message)]) message)])
(raise (exn:fail:syntax message (current-continuation-marks) (raise
(filter values (list* stx sub-stx extra-stxs)))))) (exn:fail:syntax message
(current-continuation-marks)
(if source-stx (cons source-stx extra-stxs) extra-stxs)))))
;; ---- ;; ----
;; compose-error-message : .... -> string
(define (compose-error-message who message (define (compose-error-message who message
#:continued [continued-message null] #:continued [continued-message null]
. field+detail-list) . field+detail-list)
@ -91,6 +99,13 @@ TODO
(field+detail-list->table 'compose-error-message field+detail-list null)) (field+detail-list->table 'compose-error-message field+detail-list null))
(compose* who message continued-message details)) (compose* who message continued-message details))
;; compose-error-detail : string (listof option) any -> (listof string)
;; Note: includes a leading newline (unless detail omitted).
(define (compose-error-detail field options value)
(apply string-append (compose-detail* field options value)))
;; ----
(define (compose* who message continued-message details) (define (compose* who message continued-message details)
(let* ([parts (apply append (let* ([parts (apply append
(for/list ([detail (in-list details)]) (for/list ([detail (in-list details)])
@ -98,7 +113,7 @@ TODO
[field (if (pair? field+opts) (car field+opts) field+opts)] [field (if (pair? field+opts) (car field+opts) field+opts)]
[options (if (pair? field+opts) (cdr field+opts) '())] [options (if (pair? field+opts) (cdr field+opts) '())]
[value (cdr detail)]) [value (cdr detail)])
(compose-error-detail field options value))))] (compose-detail* field options value))))]
[parts (let loop ([continued continued-message]) [parts (let loop ([continued continued-message])
(cond [(pair? continued) (list* "\n " (car continued) (loop (cdr continued)))] (cond [(pair? continued) (list* "\n " (car continued) (loop (cdr continued)))]
[(string? continued) (loop (list continued))] [(string? continued) (loop (list continued))]
@ -109,17 +124,27 @@ TODO
parts)]) parts)])
(apply string-append parts))) (apply string-append parts)))
;; compose-error-detail : string (listof option) any -> (listof string) (define (compose-detail* field options value)
;; Note: includes a leading newline (unless detail omitted).
(define (compose-error-detail field options value)
(let* ([value? (memq 'value options)] (let* ([value? (memq 'value options)]
[multi? (memq 'multi options)] [multi? (memq 'multi options)]
[maybe? (memq 'maybe options)] [maybe? (memq 'maybe options)]
[convert-value [noindent? (memq 'noindent options)]
[convert-value0
(cond [value? (cond [value?
(lambda (v) ((error-value->string-handler) v (error-print-width)))] (lambda (v) ((error-value->string-handler) v (error-print-width)))]
[else [else
(lambda (v) (format "~a" v))])]) (lambda (v) (format "~a" v))])]
[convert-value
(if noindent?
(lambda (v indent) (list (convert-value0 v)))
(lambda (v indent)
(let* ([s (convert-value0 v)]
[lines (string-split s #rx"[\n]" #:trim? #f)]
[spacing
(case indent
((3) "\n ") ;; common case, make constant
(else (string-append "\n" (make-string indent #\space))))])
(add-between lines spacing))))])
(cond [(and (or maybe? multi? (not value?)) (cond [(and (or maybe? multi? (not value?))
(not value)) (not value))
null] null]
@ -131,13 +156,13 @@ TODO
(let value-loop ([value value]) (let value-loop ([value value])
(cond [(pair? value) (cond [(pair? value)
(list* "\n " (list* "\n "
(convert-value (car value)) (append (convert-value (car value) 3)
(value-loop (cdr value)))] (value-loop (cdr value))))]
[(null? value) [(null? value)
null])))] null])))]
[else [else
(list "\n " field ": " (list* "\n " field ": "
(convert-value value))]))) (convert-value value (+ 4 (string-length field))))])))
;; ---- ;; ----