adjust the auto-text behavior of DrRacket so that it doesn't require the
queue-callback / execute callback dance; also, change the behavior a little bit so that it works a little bit more like the rest of the DrRacket languages; in particular, the initialization of the REPL now only happens when a window is first opened or a new tab is first created, but not at other times (ie not when the language changes; when the language changes, we just keep the REPL state the same and show a warning like before) This change also required a change to the way the repl is initialized and a slight change to the behavior of the first-opened method. Specifically, it is now called in a slightly better context so that errors that happen look like errors in the user's program. The only other use of the first-opened method in the tree was to initialize the teachpacks in the teaching languages and this new behavior is also an improvement there.
This commit is contained in:
parent
ba11a02c1d
commit
bf53fd5c38
|
@ -81,6 +81,24 @@
|
||||||
(when language-info
|
(when language-info
|
||||||
(set! sandbox (make-evaluator 'racket/base)))))
|
(set! sandbox (make-evaluator 'racket/base)))))
|
||||||
|
|
||||||
|
(define/override (first-opened settings)
|
||||||
|
(define ns (get-ns (get-auto-text settings)))
|
||||||
|
(when ns (current-namespace ns)))
|
||||||
|
|
||||||
|
(define/private (get-ns str)
|
||||||
|
(define ev (make-evaluator 'racket/base))
|
||||||
|
(ev `(parameterize ([read-accept-reader #t])
|
||||||
|
(define stx (read-syntax "here" (open-input-string ,str)))
|
||||||
|
(define modname
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(module name . stuff)
|
||||||
|
`',(syntax->datum #'name)]
|
||||||
|
[_ #f]))
|
||||||
|
(and modname
|
||||||
|
(eval stx)
|
||||||
|
(namespace-require modname)
|
||||||
|
(module->namespace modname)))))
|
||||||
|
|
||||||
(inherit get-language-name)
|
(inherit get-language-name)
|
||||||
(define/public (get-users-language-name defs-text)
|
(define/public (get-users-language-name defs-text)
|
||||||
(let* ([defs-port (open-input-text-editor defs-text)]
|
(let* ([defs-port (open-input-text-editor defs-text)]
|
||||||
|
@ -278,7 +296,9 @@
|
||||||
(define repl-init-thunk (make-thread-cell #f))
|
(define repl-init-thunk (make-thread-cell #f))
|
||||||
|
|
||||||
(define/override (front-end/complete-program port settings)
|
(define/override (front-end/complete-program port settings)
|
||||||
(define (super-thunk) ((get-reader) (object-name port) port))
|
(define (super-thunk)
|
||||||
|
(define reader (get-reader))
|
||||||
|
(reader (object-name port) port))
|
||||||
(define path
|
(define path
|
||||||
(cond [(get-filename port) => (compose simplify-path cleanse-path)]
|
(cond [(get-filename port) => (compose simplify-path cleanse-path)]
|
||||||
[else #f]))
|
[else #f]))
|
||||||
|
@ -290,7 +310,7 @@
|
||||||
(let ([expr
|
(let ([expr
|
||||||
;; just reading the definitions might be a syntax error,
|
;; just reading the definitions might be a syntax error,
|
||||||
;; possibly due to bad language (eg, no foo/lang/reader)
|
;; possibly due to bad language (eg, no foo/lang/reader)
|
||||||
(with-handlers ([exn? (λ (e)
|
(with-handlers ([exn:fail? (λ (e)
|
||||||
;; [Eli] FIXME: use `read-language' on `port' after calling
|
;; [Eli] FIXME: use `read-language' on `port' after calling
|
||||||
;; `file-position' to reset it to the beginning (need to
|
;; `file-position' to reset it to the beginning (need to
|
||||||
;; make sure that it's always a seekable port), then see
|
;; make sure that it's always a seekable port), then see
|
||||||
|
@ -298,8 +318,8 @@
|
||||||
;; the port (a second reset), construct a string holding
|
;; the port (a second reset), construct a string holding
|
||||||
;; the #lang, and read from it an empty module, and extract
|
;; the #lang, and read from it an empty module, and extract
|
||||||
;; the base module from it (ask Matthew about this).
|
;; the base module from it (ask Matthew about this).
|
||||||
(raise-hopeless-exception
|
(raise-hopeless-exception
|
||||||
e "invalid module text"))])
|
e "invalid module text"))])
|
||||||
(super-thunk))])
|
(super-thunk))])
|
||||||
(when (eof-object? expr) (raise-hopeless-syntax-error))
|
(when (eof-object? expr) (raise-hopeless-syntax-error))
|
||||||
(let ([more (super-thunk)])
|
(let ([more (super-thunk)])
|
||||||
|
@ -471,7 +491,7 @@
|
||||||
(custodian-shutdown-all (send rep get-user-custodian)))
|
(custodian-shutdown-all (send rep get-user-custodian)))
|
||||||
|
|
||||||
(define (raise-hopeless-syntax-error . error-args)
|
(define (raise-hopeless-syntax-error . error-args)
|
||||||
(with-handlers ([exn? raise-hopeless-exception])
|
(with-handlers ([exn:fail? raise-hopeless-exception])
|
||||||
(apply raise-syntax-error '|Module Language|
|
(apply raise-syntax-error '|Module Language|
|
||||||
(if (null? error-args)
|
(if (null? error-args)
|
||||||
(list (string-append
|
(list (string-append
|
||||||
|
|
|
@ -1674,34 +1674,29 @@ TODO
|
||||||
(thaw-colorer)
|
(thaw-colorer)
|
||||||
(send context disable-evaluation)
|
(send context disable-evaluation)
|
||||||
(reset-console)
|
(reset-console)
|
||||||
|
|
||||||
(let ([exn-raised #f]
|
|
||||||
[lang (drracket:language-configuration:language-settings-language user-language-settings)])
|
|
||||||
(queue-user/wait
|
|
||||||
(λ () ; =User=, =No-Breaks=
|
|
||||||
(with-handlers ((exn:fail? (λ (x) (set! exn-raised x))))
|
|
||||||
(cond
|
|
||||||
;; this is for backwards compatibility; drracket used to
|
|
||||||
;; expect this method to be a thunk (but that was a bad decision)
|
|
||||||
[(object-method-arity-includes? lang 'first-opened 1)
|
|
||||||
(send lang first-opened
|
|
||||||
(drracket:language-configuration:language-settings-settings user-language-settings))]
|
|
||||||
[else
|
|
||||||
;; this is the backwards compatible case.
|
|
||||||
(send lang first-opened)]))))
|
|
||||||
(when exn-raised
|
|
||||||
(let ([sp (open-output-string)])
|
|
||||||
(parameterize ([current-error-port sp])
|
|
||||||
(drracket:init:original-error-display-handler (exn-message exn-raised) exn-raised))
|
|
||||||
(message-box (string-constant drscheme)
|
|
||||||
(format "Exception raised while running the first-opened method of the language ~s:\n~a"
|
|
||||||
(send lang get-language-position)
|
|
||||||
(get-output-string sp))))))
|
|
||||||
|
|
||||||
(insert-prompt)
|
(insert-prompt)
|
||||||
(send context enable-evaluation)
|
|
||||||
(end-edit-sequence)
|
(let ([lang (drracket:language-configuration:language-settings-language user-language-settings)]
|
||||||
(clear-undos))
|
[drr-evtspace (current-eventspace)])
|
||||||
|
(run-in-evaluation-thread
|
||||||
|
(λ ()
|
||||||
|
(let/ec k
|
||||||
|
(parameterize ([error-escape-handler (λ () (k (void)))])
|
||||||
|
(cond
|
||||||
|
;; this is for backwards compatibility; drracket used to
|
||||||
|
;; expect this method to be a thunk (but that was a bad decision)
|
||||||
|
[(object-method-arity-includes? lang 'first-opened 1)
|
||||||
|
(send lang first-opened
|
||||||
|
(drracket:language-configuration:language-settings-settings user-language-settings))]
|
||||||
|
[else
|
||||||
|
;; this is the backwards compatible case.
|
||||||
|
(send lang first-opened)])))
|
||||||
|
(parameterize ([current-eventspace drr-evtspace])
|
||||||
|
(queue-callback
|
||||||
|
(λ ()
|
||||||
|
(send context enable-evaluation)
|
||||||
|
(end-edit-sequence)
|
||||||
|
(clear-undos))))))))
|
||||||
|
|
||||||
(define indenting-limit 0)
|
(define indenting-limit 0)
|
||||||
(define/override (get-limit n)
|
(define/override (get-limit n)
|
||||||
|
|
|
@ -51,6 +51,11 @@ module browser threading seems wrong.
|
||||||
|
|
||||||
(define define-button-long-label "(define ...)")
|
(define define-button-long-label "(define ...)")
|
||||||
|
|
||||||
|
(define oprintf
|
||||||
|
(let ([op (current-output-port)])
|
||||||
|
(λ args
|
||||||
|
(apply fprintf op args))))
|
||||||
|
|
||||||
(define-unit unit@
|
(define-unit unit@
|
||||||
(import [prefix help-desk: drracket:help-desk^]
|
(import [prefix help-desk: drracket:help-desk^]
|
||||||
[prefix drracket:app: drracket:app^]
|
[prefix drracket:app: drracket:app^]
|
||||||
|
@ -76,7 +81,8 @@ module browser threading seems wrong.
|
||||||
set-visible-defs
|
set-visible-defs
|
||||||
set-focus-d/i
|
set-focus-d/i
|
||||||
get-i
|
get-i
|
||||||
set-i)
|
set-i
|
||||||
|
insert-auto-text)
|
||||||
(define tab<%>
|
(define tab<%>
|
||||||
(interface (drracket:rep:context<%>)
|
(interface (drracket:rep:context<%>)
|
||||||
get-frame
|
get-frame
|
||||||
|
@ -693,7 +699,12 @@ module browser threading seems wrong.
|
||||||
(define/pubment (already-warned)
|
(define/pubment (already-warned)
|
||||||
(set! already-warned-state #t))
|
(set! already-warned-state #t))
|
||||||
|
|
||||||
|
;; the really-modified? flag determines if there
|
||||||
|
;; is a modification that is not the insertion of the auto-text
|
||||||
(define really-modified? #f)
|
(define really-modified? #f)
|
||||||
|
|
||||||
|
;; when this flag is #t, edits to the buffer do not count as
|
||||||
|
;; user's edits and so the yellow warning does not appear
|
||||||
(define ignore-edits? #f)
|
(define ignore-edits? #f)
|
||||||
|
|
||||||
(define/augment (after-insert x y)
|
(define/augment (after-insert x y)
|
||||||
|
@ -776,7 +787,7 @@ module browser threading seems wrong.
|
||||||
(not (is-modified?))
|
(not (is-modified?))
|
||||||
(not (get-filename))))
|
(not (get-filename))))
|
||||||
;; inserts the auto-text if any, and executes the text if so
|
;; inserts the auto-text if any, and executes the text if so
|
||||||
(define/private (insert-auto-text)
|
(define/public (insert-auto-text)
|
||||||
(define lang
|
(define lang
|
||||||
(drracket:language-configuration:language-settings-language
|
(drracket:language-configuration:language-settings-language
|
||||||
next-settings))
|
next-settings))
|
||||||
|
@ -788,20 +799,13 @@ module browser threading seems wrong.
|
||||||
(drracket:language-configuration:language-settings-settings
|
(drracket:language-configuration:language-settings-settings
|
||||||
next-settings))))
|
next-settings))))
|
||||||
(when auto-text
|
(when auto-text
|
||||||
|
(set! ignore-edits? #t)
|
||||||
(begin-edit-sequence #f)
|
(begin-edit-sequence #f)
|
||||||
(insert auto-text)
|
(insert auto-text)
|
||||||
(set-modified #f)
|
(set-modified #f)
|
||||||
|
(set! ignore-edits? #f)
|
||||||
(end-edit-sequence)
|
(end-edit-sequence)
|
||||||
(set! really-modified? #f)
|
(set! really-modified? #f)))
|
||||||
;; HACK: click run; would be better to override on-execute and
|
|
||||||
;; make it initialize a working repl, but the problem is that
|
|
||||||
;; doing that in module-language.rkt means that it'll either need
|
|
||||||
;; to find if the current text is the auto-text and analyze it to
|
|
||||||
;; get this initialization, or it will need to do that for all
|
|
||||||
;; possible contents, which means that it'll work when opening
|
|
||||||
;; exiting files too (it might be feasible once we have a #lang
|
|
||||||
;; parser).
|
|
||||||
(send (get-top-level-window) execute-callback)))
|
|
||||||
(define/private (remove-auto-text)
|
(define/private (remove-auto-text)
|
||||||
(when (and (not really-modified?)
|
(when (and (not really-modified?)
|
||||||
(not (get-filename))
|
(not (get-filename))
|
||||||
|
@ -821,8 +825,6 @@ module browser threading seems wrong.
|
||||||
|
|
||||||
(super-new [show-line-numbers? (show-line-numbers?)])
|
(super-new [show-line-numbers? (show-line-numbers?)])
|
||||||
|
|
||||||
;; insert the default-text
|
|
||||||
(queue-callback (lambda () (insert-auto-text)))
|
|
||||||
(highlight-first-line
|
(highlight-first-line
|
||||||
(is-a? (drracket:language-configuration:language-settings-language next-settings)
|
(is-a? (drracket:language-configuration:language-settings-language next-settings)
|
||||||
drracket:module-language:module-language<%>))
|
drracket:module-language:module-language<%>))
|
||||||
|
@ -2708,7 +2710,8 @@ module browser threading seems wrong.
|
||||||
(send defs set-interactions-text ints)
|
(send defs set-interactions-text ints)
|
||||||
(send defs set-tab tab)
|
(send defs set-tab tab)
|
||||||
(send ints set-definitions-text defs)
|
(send ints set-definitions-text defs)
|
||||||
(send defs change-mode-to-match)))
|
(send defs change-mode-to-match)
|
||||||
|
(send defs insert-auto-text)))
|
||||||
|
|
||||||
|
|
||||||
;
|
;
|
||||||
|
@ -4647,12 +4650,12 @@ module browser threading seems wrong.
|
||||||
(define (create-new-drscheme-frame filename)
|
(define (create-new-drscheme-frame filename)
|
||||||
(let* ([drs-frame% (drracket:get/extend:get-unit-frame)]
|
(let* ([drs-frame% (drracket:get/extend:get-unit-frame)]
|
||||||
[frame (new drs-frame% (filename filename))])
|
[frame (new drs-frame% (filename filename))])
|
||||||
(send (send frame get-interactions-text) initialize-console)
|
|
||||||
(when first-frame?
|
(when first-frame?
|
||||||
(let ([pos (preferences:get 'drracket:frame:initial-position)])
|
(let ([pos (preferences:get 'drracket:frame:initial-position)])
|
||||||
(when pos
|
(when pos
|
||||||
(send frame move (car pos) (cdr pos)))))
|
(send frame move (car pos) (cdr pos)))))
|
||||||
(send frame update-toolbar-visibility)
|
(send frame update-toolbar-visibility)
|
||||||
(send frame show #t)
|
(send frame show #t)
|
||||||
|
(send (send frame get-interactions-text) initialize-console)
|
||||||
(set! first-frame? #f)
|
(set! first-frame? #f)
|
||||||
frame)))
|
frame)))
|
||||||
|
|
|
@ -432,8 +432,7 @@
|
||||||
|
|
||||||
(define/override (first-opened settings)
|
(define/override (first-opened settings)
|
||||||
(for ([tp (in-list (htdp-lang-settings-teachpacks settings))])
|
(for ([tp (in-list (htdp-lang-settings-teachpacks settings))])
|
||||||
(with-handlers ((exn:fail? void)) ;; swallow errors here; drracket is not ready to display errors at this point
|
(for-each namespace-require/constant tp)))
|
||||||
(for-each namespace-require/constant tp))))
|
|
||||||
|
|
||||||
(inherit get-module get-transformer-module get-init-code
|
(inherit get-module get-transformer-module get-init-code
|
||||||
use-namespace-require/copy?)
|
use-namespace-require/copy?)
|
||||||
|
|
|
@ -628,25 +628,27 @@ default settings obtained via
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@defmethod*[([(first-opened [settings settings]) void?]
|
@defmethod*[([(first-opened [settings settings]) void?])]{
|
||||||
[(first-opened) void?])]{
|
|
||||||
|
|
||||||
This method is called when the language is initialized, but
|
This method is called after the language is initialized, but
|
||||||
no program is run. It is called from the user's eventspace's
|
no program has yet been run. It is called from the user's
|
||||||
main thread.
|
eventspace's main thread.
|
||||||
|
|
||||||
See also
|
See also
|
||||||
@method[drracket:rep:text% initialize-console].
|
@method[drracket:rep:text% initialize-console].
|
||||||
|
|
||||||
Calling this method should not raise an exception (or otherwise
|
Calling this method should not raise an exception (or otherwise
|
||||||
try to escape). DrRacket is not in a position to signal the errors
|
try to escape). DrRacket calls this method in a @racket[parameterize]
|
||||||
as user errors when this is called. An error will cause DrRacket
|
where the @racket[error-escape-handler] is set to an escaping
|
||||||
to hang.
|
continuation that continues initializing the interactions window.
|
||||||
|
Thus, raising an exception will report the error in the user's
|
||||||
|
interactions window as if this were a bug in the user's program.
|
||||||
|
Escaping in any other way, however, can cause DrRacket to fail
|
||||||
|
to start up.
|
||||||
|
|
||||||
Contrary to the method contract space, this method
|
Contrary to the method contract space, DrRacket will also invoke this
|
||||||
does not have to accept both zero and one arguments; the zero argument
|
method if it has zero arguments, passing nothing; the zero argument
|
||||||
version is for backwards compatibility and drracket tests the arity of the
|
version is for backwards compatibility and is not recommended.
|
||||||
method before invoking it.
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,8 +217,7 @@ See also
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@defmethod[(initialize-console)
|
@defmethod[(initialize-console) void?]{
|
||||||
void?]{
|
|
||||||
|
|
||||||
This inserts the ``Welcome to DrRacket'' message into the interactions
|
This inserts the ``Welcome to DrRacket'' message into the interactions
|
||||||
buffer, calls
|
buffer, calls
|
||||||
|
@ -227,12 +226,22 @@ buffer, calls
|
||||||
@method[editor<%> clear-undos].
|
@method[editor<%> clear-undos].
|
||||||
|
|
||||||
Once the console is initialized, this method calls
|
Once the console is initialized, this method calls
|
||||||
@method[drracket:language:language<%> first-opened]. Accordingly, this method should not be called to initialize
|
@method[drracket:language:language<%> first-opened].
|
||||||
|
Accordingly, this method should not be called to initialize
|
||||||
a REPL when the user's evaluation is imminent. That is,
|
a REPL when the user's evaluation is imminent. That is,
|
||||||
this method should be called when new tabs or new windows
|
this method should be called when new tabs or new windows
|
||||||
are created, but not when the Run button is clicked.
|
are created, but not when the Run button is clicked.
|
||||||
|
|
||||||
|
This method calls the
|
||||||
|
@method[drracket:language:language<%> first-opened]
|
||||||
|
from the user's eventspace's main thread and, when
|
||||||
|
@method[drracket:language:language<%> first-opened]
|
||||||
|
returns, it enqueue's a callback that ends
|
||||||
|
an edit sequence on the REPL and calls
|
||||||
|
@method[editor<%> clear-undos]. Accordingly, if the
|
||||||
|
@method[drracket:language:language<%> first-opened]
|
||||||
|
method does not return, the interactions text will
|
||||||
|
be in an unclosed edit sequence.
|
||||||
}
|
}
|
||||||
|
|
||||||
@defmethod[(insert-prompt)
|
@defmethod[(insert-prompt)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user