hash-lang,repl: GUIs are not interactive
Bogdanp opened this issue · comments
((alist-get 'racket-mode package-alist)) ((emacs-version "29.1") (system-type darwin) (x-gtk-use-system-tooltips UNDEFINED) (major-mode help-mode) (racket--el-source-dir "/Users/bogdan/.emacs.d/vendor/racket-mode/") (racket--rkt-source-dir "/Users/bogdan/.emacs.d/vendor/racket-mode/racket/") (racket-program "racket") (racket-command-timeout 10) (racket-path-from-emacs-to-racket-function UNDEFINED) (racket-path-from-racket-to-emacs-function UNDEFINED) (racket-browse-url-function racket-browse-url-using-temporary-file) (racket-documentation-search-location "https://docs.racket-lang.org/search/index.html?q=%s") (racket-xp-after-change-refresh-delay 1) (racket-xp-mode-lighter (:eval (racket--xp-mode-lighter))) (racket-xp-highlight-unused-regexp "^[^_]") (racket-repl-buffer-name-function racket-repl-buffer-name-project) (racket-submodules-to-run ((test) (main))) (racket-memory-limit 2048) (racket-error-context medium) (racket-repl-history-directory "~/.emacs.d/racket-mode/") (racket-history-filter-regexp "\\`\\s *\\'") (racket-images-inline t) (racket-imagemagick-props nil) (racket-images-keep-last 100) (racket-images-system-viewer "open") (racket-pretty-print t) (racket-use-repl-submit-predicate nil) (racket-pretty-print t) (racket-indent-curly-as-sequence t) (racket-indent-sequence-depth 0) (racket-pretty-lambda nil) (racket-smart-open-bracket-enable nil) (racket-module-forms "\\s(\\(?:module[*+]?\\|library\\)") (racket-logger-config ((cm-accomplice . warning) (GC . info) (module-prefetch . warning) (optimizer . info) (racket/contract . error) (racket-mode-debugger . info) (sequence-specialization . info) (* . fatal))) (racket-show-functions (racket-show-echo-area))) (enabled-minor-modes (auto-composition-mode) (auto-compression-mode) (auto-encryption-mode) (auto-fill-mode) (auto-save-mode) (buffer-read-only) (column-number-mode) (dumb-jump-mode) (electric-indent-mode) (evil-local-mode) (evil-mode) (evil-surround-mode) (file-name-shadow-mode) (flx-ido-mode) (font-lock-mode) (global-auto-revert-mode) (global-eldoc-mode) (global-evil-surround-mode) (global-font-lock-mode) (global-hl-line-mode) (ido-everywhere) (ido-ubiquitous-mode) (ido-vertical-mode) (isearch-fold-quotes-mode) (line-number-mode) (mac-mouse-wheel-mode) (menu-bar-mode) (override-global-mode) (projectile-mode) (recentf-mode) (save-place-mode) (savehist-mode) (semantic-minor-modes-format) (server-mode) (shell-dirtrack-mode) (show-paren-mode) (transient-mark-mode) (windmove-mode)) (disabled-minor-modes (abbrev-mode) (auto-fill-function) (auto-image-file-mode) (auto-revert-mode) (auto-revert-tail-mode) (auto-save-visited-mode) (blink-cursor-mode) (buffer-face-mode) (button-mode) (cl-old-struct-compat-mode) (comint-fontify-input-mode) (company-mode) (company-search-mode) (compilation-minor-mode) (compilation-shell-minor-mode) (completion-in-region-mode) (context-menu-mode) (cursor-face-highlight-mode) (dash-fontify-mode) (defining-kbd-macro) (diff-auto-refine-mode) (diff-minor-mode) (dired-hide-details-mode) (dired-isearch-filenames-mode) (dired-omit-mode) (diredp-breadcrumbs-in-header-line-mode) (edit-indirect--overlay) (eldoc-mode) (electric-layout-mode) (electric-quote-mode) (eshell-arg-mode) (eshell-command-mode) (eshell-proc-mode) (flycheck-mode) (flyspell-mode) (global-company-mode) (global-dash-fontify-mode) (global-dired-hide-details-mode) (global-flycheck-mode) (global-prettify-symbols-mode) (global-reveal-mode) (global-semantic-highlight-edits-mode) (global-semantic-highlight-func-mode) (global-semantic-show-parser-state-mode) (global-semantic-show-unmatched-syntax-mode) (global-semantic-stickyfunc-mode) (global-visual-line-mode) (hl-line-mode) (horizontal-scroll-bar-mode) (hs-minor-mode) (ibuffer-auto-mode) (ido-cr+-debug-mode) (image-minor-mode) (indent-tabs-mode) (isearch-mode) (ispell-minor-mode) (jit-lock-debug-mode) (lock-file-mode) (lost-selection-mode) (mac-auto-ascii-mode) (mac-auto-operator-composition-mode) (mac-font-panel-mode) (minibuffer-electric-default-mode) (mouse-wheel-mode) (next-error-follow-minor-mode) (overwrite-mode) (paragraph-indent-minor-mode) (paredit-mode) (prettify-symbols-mode) (pyvenv-mode) (pyvenv-tracking-mode) (racket-hash-lang-repl-mode) (racket-smart-open-bracket-mode) (racket-xp-mode) (rainbow-delimiters-mode) (read-extended-command-mode) (rectangle-mark-mode) (reveal-mode) (semantic-highlight-edits-mode) (semantic-highlight-func-mode) (semantic-mode) (semantic-show-parser-state-mode) (semantic-show-unmatched-syntax-mode) (semantic-stickyfunc-mode) (sh-electric-here-document-mode) (shell-highlight-undef-mode) (size-indication-mode) (tab-bar-history-mode) (tab-bar-mode) (temp-buffer-resize-mode) (text-scale-mode) (tool-bar-mode) (tooltip-mode) (treesit-explore-mode) (treesit-inspect-mode) (undelete-frame-mode) (url-handler-mode) (use-hard-newlines) (vc-dir-git-mode) (view-mode) (visible-mode) (visual-line-mode) (window-divider-mode) (xref-etags-mode))
With the most recent REPL changes, whenever I render a GUI using racket-mode, things render fine but I can't interact with them.
Ah, my old friend, the need to yield for GUI eventspaces.
The good news is I pushed a commit to fix this. Caveat: I only tested using this minimal example from #562.
I used current-get-interaction-evt
, which @mflatt added for expeditor.
So the bad news is this requires Racket version 8.4, released Feb 2022, less than 2 years ago.
A couple commits ago, I'd felt a little guilty bumping the minimum from 6.9 to 6.12.
My policy has been to support quite old versions of Racket, even if that takes a little more work or guards a few features behind dynamic-require
checks.
Maybe there's some other way to fix this, by continuing to use current-get-interaction-input-port
, but giving it a custom make-input-port
, which would work with older versions?
Or maybe that would have its own gotchas. (I don't know if @mflatt added this as a useful simplification for such situations, or as the only realistic reliable way.)
Maybe requiring 8.4 is OK and I should relax my older versions policy.
Could you maybe copy the code here and do that yourself:
https://github.com/racket/gui/blob/master/gui-lib/mred/private/wx/common/queue.rkt#L643-L666
@samth I don't think so because the thread-cell handler-thread-of
is private.
I don't yet understand it well enough to see if there might be some way to implement the equivalent in terms of provided definitions.
Wait, can I simply use yield
instead of sync
??
I have a channel of strings (REPL submissions), and my prompt-read
does (channel-get ch)
instead of reading from an input port. That was my starting point.
So I could change (channel-get ch)
to (sync ch)
and that still works, of course.
Now if racket/gui
is loaded, can I simply change (sync ch)
to (yield ch)
? The docs seem to say so. My quick experiment shows "it works". But does it work?
p.s. I already have a "txt/gui" macro:
;; Like mz/mr from racket/sandbox.
(define-syntax txt/gui
(syntax-rules ()
[(_ txtval guisym)
(if (gui-available?)
(dynamic-require 'racket/gui/base 'guisym)
txtval)]))
So in full, the helper used by my prompt-read would change:
(define (get-interaction prompt)
(repl-output-prompt (string-append prompt ">"))
- (let loop ()
- (sync
- (wrap-evt ((current-get-interaction-evt)) ;allow GUI yield
- (λ (thk) (thk) (loop)))
- (wrap-evt (current-submissions)
- (λ (str)
- (define in (open-input-string str))
- (with-stack-checkpoint
- ((current-read-interaction) 'racket-mode-repl in)))))))
+ (define str ((txt/gui sync yield) (current-submissions)))
+ (define in (open-input-string str))
+ (with-stack-checkpoint
+ ((current-read-interaction) 'racket-mode-repl in)))
I can confirm that the last patch also works and that it seems fine AFAIU. Re. the implementation that uses current-get-interaction-evt
, if you're going to stick with it instead, I'd probably use handle-evt
instead of wrap-evt
, if you're going to loop inside the wrapper procedure, otherwise the stack can grow unbounded since the wrapper argument to wrap-evt
is not called in tail position with respect to the sync.
@greghendershott this is resolved for me so I'm happy to close the issue, but I'll leave it up to you in case you want to keep it open for discussion, etc. Thanks for the fix!