misc improvements around read-language (uses and docs)

- make a logger for drracket-related #lang problems
- change read-language's docs to indicate that it can return #f
- adjust a bunch of calls to read-language for the case that it returns #f
  with the goal of making that be the same as a get-info function that
  always returns the given default
- mention `read-language` in the guide section entitled
 "Source-Handling Configuration"
This commit is contained in:
Robby Findler 2014-07-22 03:14:12 -05:00
parent 017480c9b9
commit 8429f3e9d6
8 changed files with 112 additions and 97 deletions

View File

@ -60,9 +60,10 @@
(or (looks-like-new-module-style? text) (or (looks-like-new-module-style? text)
(looks-like-old-module-style? text) (looks-like-old-module-style? text)
(with-handlers ((exn:fail? (λ (x) #f))) (with-handlers ((exn:fail? (λ (x) #f)))
(procedure? (begin
(read-language (open-input-text-editor text 0 'end (λ (x) x) text #f) (read-language (open-input-text-editor text 0 'end (λ (x) x) text #f)
(λ () #f)))))) (λ () #f))
#t))))
(: looks-like-old-module-style? ((Instance Text%) -> Boolean)) (: looks-like-old-module-style? ((Instance Text%) -> Boolean))
(define (looks-like-old-module-style? text) (define (looks-like-old-module-style? text)

View File

@ -1483,7 +1483,8 @@
(define prt (open-input-text-editor definitions-text)) (define prt (open-input-text-editor definitions-text))
(port-count-lines! prt) (port-count-lines! prt)
(define l (with-handlers ((exn:fail? (λ (x) #f))) (define l (with-handlers ((exn:fail? (λ (x) #f)))
(read-language prt))) (read-language prt)
#t))
(cond (cond
[l [l
(define-values (line col pos) (port-next-location prt)) (define-values (line col pos) (port-next-location prt))

View File

@ -104,6 +104,8 @@
(when (send defs get-in-module-language?) (when (send defs get-in-module-language?)
(send defs move-to-new-language)))))) (send defs move-to-new-language))))))
(define-logger drracket-language)
(define definitions-text-mixin (define definitions-text-mixin
(mixin (text:basic<%> (mixin (text:basic<%>
drracket:unit:definitions-text<%> drracket:unit:definitions-text<%>
@ -168,94 +170,98 @@
(clear-things-out)]))) (clear-things-out)])))
(define/public (move-to-new-language) (define/public (move-to-new-language)
(let* ([port (open-input-text-editor this)] (define port (open-input-text-editor this))
;; info-result :
;; (or/c #f [#lang without a known language]
;; (vector <get-info-proc>)
;; [no #lang line, so we use the '#lang racket' info proc]
;; <get-info-proc>) [the get-info proc for the program in the definitions]
[info-result
(with-handlers ([exn:fail?
(λ (x)
(log-debug
(format
"DrRacket: error duing call to read-language for ~a:\n ~a"
(or (send this get-filename) "<<unsaved file>>")
(regexp-replace* #rx"\n(.)" (exn-message x) "\n\\1 ")))
#f)])
(read-language
port
(lambda ()
;; fall back to whatever #lang racket does if
;; we don't have a #lang line present in the file
(vector (read-language (open-input-string "#lang racket"))))))])
; sometimes I get eof here, but I don't know why and can't seem to (define (fallback)
;; make it happen outside of DrRacket ;; fall back to whatever #lang racket does if
(when (eof-object? info-result) ;; we don't have a #lang line present in the file
(eprintf "file ~s produces eof from read-language\n" (log-drracket-language-debug "falling back to using #lang racket's read-language for ~a"
(send this get-filename)) (or (send this get-filename) "<<unsaved file>>"))
(eprintf " port-next-location ~s\n" (vector (read-language (open-input-string "#lang racket"))))
(call-with-values (λ () (port-next-location port)) list))
(eprintf " str ~s\n"
(let ([s (send this get-text)])
(substring s 0 (min 100 (string-length s)))))
(set! info-result #f))
(let-values ([(line col pos) (port-next-location port)])
(unless (equal? (get-text 0 pos) hash-lang-language)
(set! hash-lang-language (get-text 0 pos))
(set! hash-lang-last-location pos)
(clear-things-out)
(define info-proc
(if (vector? info-result)
(vector-ref info-result 0)
info-result))
(define (ctc-on-info-proc-result ctc res)
(contract ctc
res
(if (vector? info-result)
'hash-lang-racket
(get-lang-name pos))
'drracket/private/module-language-tools))
(define lang-wants-big-defs/ints-labels? ;; info-result :
(and info-proc (info-proc 'drracket:show-big-defs/ints-labels #f))) ;; (or/c #f [#lang without a known language]
(set-lang-wants-big-defs/ints-labels? lang-wants-big-defs/ints-labels?) ;; (vector <get-info-proc>)
(send (send (get-tab) get-ints) set-lang-wants-big-defs/ints-labels? ;; [no #lang line, so we use the '#lang racket' info proc]
lang-wants-big-defs/ints-labels?) ;; <get-info-proc>) [the get-info proc for the program in the definitions]
(define info-result
(with-handlers ([exn:fail?
(λ (x)
(log-drracket-language-debug
(format
"DrRacket: error duing call to read-language for ~a:\n ~a"
(or (send this get-filename) "<<unsaved file>>")
(regexp-replace* #rx"\n(.)" (exn-message x) "\n\\1 ")))
#f)])
(or (read-language port fallback)
(fallback))))
(set! extra-default-filters ; sometimes I get eof here, but I don't know why and can't seem to
(if info-result ;; make it happen outside of DrRacket
(or (ctc-on-info-proc-result (when (eof-object? info-result)
(or/c #f (listof (list/c string? string?))) (eprintf "file ~s produces eof from read-language\n"
(info-proc 'drracket:default-filters #f)) (send this get-filename))
'()) (eprintf " port-next-location ~s\n"
'())) (call-with-values (λ () (port-next-location port)) list))
(eprintf " str ~s\n"
(let ([s (send this get-text)])
(substring s 0 (min 100 (string-length s)))))
(set! info-result #f))
(define-values (line col pos) (port-next-location port))
(unless (equal? (get-text 0 pos) hash-lang-language)
(set! hash-lang-language (get-text 0 pos))
(set! hash-lang-last-location pos)
(clear-things-out)
(define info-proc
(if (vector? info-result)
(vector-ref info-result 0)
info-result))
(define (ctc-on-info-proc-result ctc res)
(contract ctc
res
(if (vector? info-result)
'hash-lang-racket
(get-lang-name pos))
'drracket/private/module-language-tools))
(set! default-extension (define lang-wants-big-defs/ints-labels?
(if info-result (and info-proc (info-proc 'drracket:show-big-defs/ints-labels #f)))
(or (ctc-on-info-proc-result (set-lang-wants-big-defs/ints-labels? lang-wants-big-defs/ints-labels?)
(or/c #f (and/c string? (not/c #rx"[.]"))) (send (send (get-tab) get-ints) set-lang-wants-big-defs/ints-labels?
(info-proc 'drracket:default-extension #f)) lang-wants-big-defs/ints-labels?)
"")
""))
(when info-result (set! extra-default-filters
(register-new-buttons (if info-result
(ctc-on-info-proc-result (or (ctc-on-info-proc-result
(or/c #f (listof (or/c (list/c string? (or/c #f (listof (list/c string? string?)))
(is-a?/c bitmap%) (info-proc 'drracket:default-filters #f))
(-> (is-a?/c drracket:unit:frame<%>) any)) '())
(list/c string? '()))
(is-a?/c bitmap%)
(-> (is-a?/c drracket:unit:frame<%>) any) (set! default-extension
(or/c real? #f))))) (if info-result
(or (info-proc 'drracket:toolbar-buttons #f) (or (ctc-on-info-proc-result
(info-proc 'drscheme:toolbar-buttons #f))) (or/c #f (and/c string? (not/c #rx"[.]")))
(ctc-on-info-proc-result (info-proc 'drracket:default-extension #f))
(or/c #f (listof symbol?)) "")
(or (info-proc 'drracket:opt-out-toolbar-buttons '()) ""))
(info-proc 'drscheme:opt-out-toolbar-buttons '())))))))))
(when info-result
(register-new-buttons
(ctc-on-info-proc-result
(or/c #f (listof (or/c (list/c string?
(is-a?/c bitmap%)
(-> (is-a?/c drracket:unit:frame<%>) any))
(list/c string?
(is-a?/c bitmap%)
(-> (is-a?/c drracket:unit:frame<%>) any)
(or/c real? #f)))))
(or (info-proc 'drracket:toolbar-buttons #f)
(info-proc 'drscheme:toolbar-buttons #f)))
(ctc-on-info-proc-result
(or/c #f (listof symbol?))
(or (info-proc 'drracket:opt-out-toolbar-buttons '())
(info-proc 'drscheme:opt-out-toolbar-buttons '())))))))
(define/private (register-new-buttons buttons opt-out-ids) (define/private (register-new-buttons buttons opt-out-ids)

View File

@ -244,7 +244,10 @@ as the @racket[_key] argument to the @racket[_get-info] function to do so:
@item{@language-info-ref[color-lexer]}] @item{@language-info-ref[color-lexer]}]
If the call to @racket[read-language] raises an error, DrRacket logs the If the call to @racket[read-language] raises an error, DrRacket logs the
error via @racket[log-debug]. error at the @racket[_debug] level to a logger with the name
@racket['drracket-language] (see
@secref["logging" #:doc '(lib "scribblings/reference/reference.scrbl")] for more
about how to follow specific loggers).
@language-info-def[color-lexer]{ @language-info-def[color-lexer]{
When a language's @racket[_get-info] procedure responds to @racket['color-lexer], it When a language's @racket[_get-info] procedure responds to @racket['color-lexer], it

View File

@ -312,7 +312,8 @@ racket
This revised @racket[literal] implementation provides a This revised @racket[literal] implementation provides a
@racketidfont{get-info} function. The @racketidfont{get-info} function @racketidfont{get-info} function. The @racketidfont{get-info} function
will be applied to the source input stream and location information, is called by @racket[read-language] (which DrRacket calls) with the
source input stream and location information,
in case query results should depend on the content of the module after in case query results should depend on the content of the module after
the language name (which is not the case for @racket[literal]). The the language name (which is not the case for @racket[literal]). The
result of @racketidfont{get-info} is a function of two arguments. The result of @racketidfont{get-info} is a function of two arguments. The

View File

@ -107,7 +107,7 @@ See @secref["readtables"] for an extended example that uses
@defproc[(read-language [in input-port? (current-input-port)] @defproc[(read-language [in input-port? (current-input-port)]
[fail-thunk (-> any) (lambda () (error ...))]) [fail-thunk (-> any) (lambda () (error ...))])
(any/c any/c . -> . any)]{ (or/c (any/c any/c . -> . any) #f)]{
Reads from @racket[in] in the same way as @racket[read], but stopping as Reads from @racket[in] in the same way as @racket[read], but stopping as
soon as a @tech{reader language} (or its absence) is determined. soon as a @tech{reader language} (or its absence) is determined.
@ -125,12 +125,13 @@ or @litchar{#!}.
When it finds a @litchar{#lang} or @litchar{#!} specification, instead When it finds a @litchar{#lang} or @litchar{#!} specification, instead
of dispatching to a @racketidfont{read} or @racketidfont{read-syntax} of dispatching to a @racketidfont{read} or @racketidfont{read-syntax}
function as @racket[read] and @racket[read-syntax] do, function as @racket[read] and @racket[read-syntax] do,
@racket[read-language] dispatches to a @racketidfont{get-info} @racket[read-language] dispatches to the @racketidfont{get-info}
function (if any) exported by the same module. The result of the function (if any) exported by the same module. The result of the
@racketidfont{get-info} function is the result of @racketidfont{get-info} function is the result of
@racket[read-language] if it is a function of two arguments; if @racket[read-language] if it is a function of two arguments; if
@racketidfont{get-info} produces any other kind of result, the @racketidfont{get-info} produces any other kind of result, the
@exnraise[exn:fail:contract]. @exnraise[exn:fail:contract]. If no @racketidfont{get-info} function is
exported, @racket[read-language] returns @racket[#f].
The function produced by @racketidfont{get-info} reflects information The function produced by @racketidfont{get-info} reflects information
about the expected syntax of the input stream. The first argument to the about the expected syntax of the input stream. The first argument to the

View File

@ -54,7 +54,9 @@ to delegate to the scheme-lexer (in the 'no-lang-line mode).
(set-port-next-location-from in p) (set-port-next-location-from in p)
(set-port-next-location-from in name-p) (set-port-next-location-from in name-p)
(define-values (_1 _2 start-pos) (port-next-location p)) (define-values (_1 _2 start-pos) (port-next-location p))
(define get-info (with-handlers ([exn:fail? values]) (read-language p (λ () 'fail)))) (define get-info (with-handlers ([exn:fail? values])
(or (read-language p (λ () 'fail))
(λ (x y) y))))
(define-values (_3 _4 end-pos) (port-next-location p)) (define-values (_3 _4 end-pos) (port-next-location p))
(cond (cond
[(procedure? get-info) [(procedure? get-info)

View File

@ -1978,7 +1978,7 @@
[read-syntax (->opt [Univ -Input-Port] (Un (-Syntax Univ) (-val eof)))] [read-syntax (->opt [Univ -Input-Port] (Un (-Syntax Univ) (-val eof)))]
[read/recursive (->opt [-Input-Port (-opt -Char) (-opt -Read-Table) Univ] Univ)] [read/recursive (->opt [-Input-Port (-opt -Char) (-opt -Read-Table) Univ] Univ)]
[read-syntax/recursive (->opt [Univ -Input-Port (-opt -Char) (-opt -Read-Table) Univ] Univ)] [read-syntax/recursive (->opt [Univ -Input-Port (-opt -Char) (-opt -Read-Table) Univ] Univ)]
[read-language (->opt [-Input-Port (-> ManyUniv)] (-> Univ Univ ManyUniv))] [read-language (->opt [-Input-Port (-> ManyUniv)] (-opt (-> Univ Univ ManyUniv)))]
[read-case-sensitive (-Param Univ B)] [read-case-sensitive (-Param Univ B)]
[read-square-bracket-as-paren (-Param Univ B)] [read-square-bracket-as-paren (-Param Univ B)]