greghendershott / racket-mode

Emacs major and minor modes for Racket: edit, REPL, check-syntax, debug, profile, and more.

Home Page:https://www.racket-mode.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

@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.

I pushed commit 210483e as a way to avoid hard-requiring Racket 8.4. It's not ideal, but I think it's the least-worst I can do absent more information.

@Bogdanp Thanks for trying and confirming! Good point about wrap-evt; I just pushed 1b8074f to use handle-evt instead.

@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!