Skip to content

Commit b3baeeb

Browse files
Improve explanation wrt Minimal Racket; closes #744
As the main entry use a "shim" module with minimal imports, that dynamic-require's everything else under an exn handler that looks for exn:fail:syntax:missing-module. Report that to the front end, which uses a new buffer to surface a message and advice for end user -- which is much better than something flashing by the in the echo area and then only being viewable if user opens the *Messages* buffer. While we have the hood open, do something similar for the error regarding not having a sufficiently new version of Racket.
1 parent eef5e9a commit b3baeeb

File tree

3 files changed

+91
-8
lines changed

3 files changed

+91
-8
lines changed

racket-cmd.el

+47-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
;;; racket-cmd.el -*- lexical-binding: t; -*-
22

3-
;; Copyright (c) 2013-2022 by Greg Hendershott.
3+
;; Copyright (c) 2013-2022, 2025 by Greg Hendershott.
44
;; Portions Copyright (C) 1985-1986, 1999-2013 Free Software Foundation, Inc.
55

66
;; Author: Greg Hendershott
@@ -75,6 +75,7 @@ Before doing anything runs the hook `racket-stop-back-end-hook'."
7575
;; Avoid excess processes/buffers like "racket-process<1>".
7676
(when (racket--cmd-open-p)
7777
(racket--cmd-close))
78+
(racket--kill-startup-error-buffer)
7879
;; Give the process buffer the current values of some vars; see
7980
;; <https://github.com/purcell/envrc/issues/22>.
8081
(cl-letf* (((default-value 'process-environment) process-environment)
@@ -93,7 +94,7 @@ Before doing anything runs the hook `racket-stop-back-end-hook'."
9394
:sentinel #'ignore))
9495
(local-p (racket--back-end-local-p back-end))
9596
(main-dot-rkt (expand-file-name
96-
"main.rkt"
97+
"shim.rkt"
9798
(if local-p
9899
racket--rkt-source-dir
99100
(racket--ensure-updated-back-end-on-remote))))
@@ -214,6 +215,8 @@ Although mostly these are 1:1 responses to command requests, some
214215
like \"logger\", \"debug-break\", and \"hash-lang\" are
215216
notifications."
216217
(pcase response
218+
(`(startup-error ,kind ,data)
219+
(run-at-time 0.001 nil #'racket--on-startup-error kind data))
217220
(`(logger ,str)
218221
(run-at-time 0.001 nil #'racket--logger-on-notify back-end str))
219222
(`(debug-break . ,response)
@@ -362,6 +365,48 @@ in a specific namespace."
362365
(error "Unknown response to command %S from %S to %S:\n%S"
363366
command-sexpr buf name v)))))))
364367

368+
;;; Back end startup error buffer
369+
370+
(defconst racket--startup-error-buffer-name
371+
"*Racket Mode back end startup failure*")
372+
373+
(defun racket--kill-startup-error-buffer ()
374+
(let ((buf (get-buffer racket--startup-error-buffer-name)))
375+
(when (buffer-live-p buf)
376+
(kill-buffer buf))))
377+
378+
(defun racket--on-startup-error (kind data)
379+
(let ((buf (get-buffer-create racket--startup-error-buffer-name)))
380+
(with-current-buffer buf
381+
(unless (eq major-mode 'special-mode)
382+
(special-mode))
383+
(visual-line-mode 1)
384+
(let ((buffer-read-only nil))
385+
(erase-buffer)
386+
(pop-to-buffer buf)
387+
(pcase kind
388+
('missing-module
389+
(let ((url "https://racket-mode.com/#Minimal-Racket-1"))
390+
(insert "The Racket Mode back end could not start because it was unable to load the module "
391+
?' data ?' "."
392+
"\n\n"
393+
"This could be because you did not install the full \"main distribution\" of Racket, but instead installed only \"Minimal Racket\" (the default when using homebrew)."
394+
"\n\n"
395+
"In that case, you will need either to install the full main distribution, or, manually install certain additional Racket packages."
396+
"\n\n"
397+
"Please see ")
398+
(save-excursion ;leave point at start of link, for handy RET
399+
(insert-button url
400+
'url url
401+
'face 'link
402+
'follow-link t
403+
'action (lambda (button)
404+
(when-let (url (button-get button 'url))
405+
(browse-url url))))
406+
(insert "."))))
407+
(_
408+
(insert data)))))))
409+
365410
(provide 'racket-cmd)
366411

367412
;; racket-cmd.el ends here

racket/main.rkt

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
;; Copyright (c) 2013-2022 by Greg Hendershott.
1+
;; Copyright (c) 2013-2025 by Greg Hendershott.
22
;; SPDX-License-Identifier: GPL-3.0-or-later.
33

44
#lang racket/base
@@ -11,13 +11,22 @@
1111
"command-server.rkt"
1212
(only-in "image.rkt" set-use-svg?!))
1313

14+
(provide main)
15+
16+
;;;(require does-not-exist) ;;TESTING
17+
1418
(define (assert-racket-version minimum-version)
1519
(define actual-version (version))
1620
(unless (version<=? minimum-version actual-version)
17-
(error '|Racket Mode back end| "Need Racket ~a or newer but ~a is ~a"
18-
minimum-version
19-
(find-executable-path (find-system-path 'exec-file))
20-
actual-version)))
21+
;; Write a "notification" for the Emacs front end and exit.
22+
(writeln `(startup-error
23+
other
24+
,(format "Racket Mode needs Racket ~a or newer but ~a is ~a."
25+
minimum-version
26+
(find-executable-path (find-system-path 'exec-file))
27+
actual-version)))
28+
(flush-output)
29+
(exit 14)))
2130

2231
(define (macos-sequoia-or-newer?)
2332
(and (eq? 'macosx (system-type 'os))
@@ -30,7 +39,7 @@
3039
(and (valid-version? ver)
3140
(version<=? "15.0" ver))))))))
3241

33-
(module+ main
42+
(define (main)
3443
(assert-racket-version (if (macos-sequoia-or-newer?)
3544
"8.14.0.4" ;issue #722
3645
"6.12")) ;general requirement

racket/shim.rkt

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
;; Copyright (c) 2025 by Greg Hendershott.
2+
;; SPDX-License-Identifier: GPL-3.0-or-later.
3+
4+
#lang racket/base
5+
6+
;; A "shim" that handles module import errors when starting the back
7+
;; end.
8+
;;
9+
;; Motivation: Supply more-helpful information in case people are
10+
;; using Minimal Racket; #744.
11+
12+
;; Limit imports to those in Minimal Racket:
13+
(require racket/runtime-path)
14+
15+
(define-runtime-path main.rkt "main.rkt")
16+
17+
;; Write a "notification" for the Emacs front end and exit.
18+
(define (missing-module e)
19+
(writeln `(startup-error
20+
missing-module
21+
,(format "~a" (exn:fail:syntax:missing-module-path e))))
22+
(flush-output)
23+
(exit 13))
24+
25+
(module+ main
26+
(define main
27+
(with-handlers ([exn:fail:syntax:missing-module? missing-module])
28+
(dynamic-require main.rkt 'main)))
29+
(main))

0 commit comments

Comments
 (0)