From 65b8eb13d366109efd29f715682d596849f40ac5 Mon Sep 17 00:00:00 2001 From: Greg Hendershott Date: Sun, 10 Dec 2023 13:53:09 -0500 Subject: [PATCH] racket-repl: Re-implement as just running a file; closes #689 Narrowly, this fixes the kind of problem as in #689 where a setting like racket-pretty-print only takes effect via a run. Broadly, this makes this command follow the the main intended use case -- a REPL is associated with running a file. Now the command is just a shortcut for running a file with a certain name (and creating that file if it doesn't exist). Also, this fits better in a hash-lang world. If say someone mostly works with #lang rhombus, and wants "give me a quick REPL" to use that, now they can instead of getting #lang racket/base. Finally, this lets the doc string explain that the REPL is always just about running some file. If a user wanted to have "several init files", well, they're really talking about running several source files frequently, which of course they can already do. And if they want a quick key binding for each one, that's an easy customization nearly any end user can do for themselves. TL;DR: Years ago when some folks asked for a racket-repl command, this is probably how I should have done it: A trivial variation of racket-run. --- doc/generate.el | 1 + doc/racket-mode.texi | 27 ++++++++++++++------------ racket-custom.el | 9 ++++++++- racket-repl.el | 46 ++++++++++++++++++++++++++------------------ 4 files changed, 51 insertions(+), 32 deletions(-) diff --git a/doc/generate.el b/doc/generate.el index 4e482ae5..fc86e26f 100644 --- a/doc/generate.el +++ b/doc/generate.el @@ -204,6 +204,7 @@ racket-images-keep-last racket-images-system-viewer racket-pretty-print + racket-repl-command-file "Other variables" racket-indent-curly-as-sequence racket-indent-sequence-depth diff --git a/doc/racket-mode.texi b/doc/racket-mode.texi index 2b0bce48..f2b82079 100644 --- a/doc/racket-mode.texi +++ b/doc/racket-mode.texi @@ -226,6 +226,7 @@ REPL variables * racket-images-keep-last:: * racket-images-system-viewer:: * racket-pretty-print:: +* racket-repl-command-file:: Other variables @@ -2325,22 +2326,18 @@ simply the outermost, file module. Show a Racket REPL buffer in some window. -@strong{IMPORTANT} - The main, intended use of Racket Mode's REPL is that you -@code{find-file} some specific .rkt file, then run it using +@code{find-file} some specific file, then run it using a command like @ref{racket-run} or @ref{racket-run-module-at-point}. The resulting REPL will correspond to those definitions and match your expectations. -If you really want to start a REPL for no file in particular, -then you could use this @ref{racket-repl} command. But the resulting -REPL will have a minimal ``#lang racket/base'' namespace. You -could enter ``(require racket)'' if you want the equivalent of -``#lang racket''. You could also ``(require racket/enter)'' if -you want things like ``enter!''. But in some sense you'd be -``using it wrong''. If you actually don't want to use Racket -Mode's REPL as intended, then consider using a plain Emacs -@code{shell} buffer to run command-line Racket. +Therefore this @ref{racket-repl} command -- which is intended as a +convenience for people who want a way to ``just get a quick +REPL'' -- is actually implemented as just running the file named +in the customization variable @ref{racket-repl-command-file}. By +default when that file doesn't exist, it is created to contain +just ``#lang racket/base''. You may edit the file to use a +different lang, require other modules, or whatever. @node racket-repl-describe @subsection racket-repl-describe @@ -3304,6 +3301,7 @@ classic @ref{racket-mode} for rackety module languages: * racket-images-keep-last:: * racket-images-system-viewer:: * racket-pretty-print:: +* racket-repl-command-file:: @end menu @node racket-repl-buffer-name-function @@ -3401,6 +3399,11 @@ The image viewer program to use for @code{racket-view-image}. Use pretty-print instead of print in REPL@? +@node racket-repl-command-file +@subsection racket-repl-command-file + +Name of the file used by @ref{racket-repl}. + @node Other variables @section Other variables diff --git a/racket-custom.el b/racket-custom.el index 03a63971..7636e4ea 100644 --- a/racket-custom.el +++ b/racket-custom.el @@ -392,7 +392,6 @@ will use this to decide whether to submit your input, yet." :safe #'booleanp :group 'racket-repl) - (defcustom racket-before-run-hook nil "Normal hook done before various Racket Mode run commands. @@ -423,6 +422,14 @@ from the variable `racket-repl-buffer-name'." :risky t :group 'racket-repl) +(defcustom racket-repl-command-file + (expand-file-name "repl.rkt" + (locate-user-emacs-file (file-name-as-directory "racket-mode"))) + "Name of the file used by `racket-repl'." + :tag "REPL Command File" + :type 'file + :group 'racket-repl) + ;;; Other (defgroup racket-other nil diff --git a/racket-repl.el b/racket-repl.el index 36abf729..675bb5a5 100644 --- a/racket-repl.el +++ b/racket-repl.el @@ -508,30 +508,38 @@ even when the module language doesn't provide any binding for (defun racket-repl (&optional noselect) "Show a Racket REPL buffer in some window. -*IMPORTANT* - The main, intended use of Racket Mode's REPL is that you -`find-file' some specific .rkt file, then run it using +`find-file' some specific file, then run it using a command like `racket-run' or `racket-run-module-at-point'. The resulting REPL will correspond to those definitions and match your expectations. -If you really want to start a REPL for no file in particular, -then you could use this `racket-repl' command. But the resulting -REPL will have a minimal \"#lang racket/base\" namespace. You -could enter \"(require racket)\" if you want the equivalent of -\"#lang racket\". You could also \"(require racket/enter)\" if -you want things like \"enter!\". But in some sense you'd be -\"using it wrong\". If you actually don't want to use Racket -Mode's REPL as intended, then consider using a plain Emacs -`shell' buffer to run command-line Racket." +Therefore this `racket-repl' command -- which is intended as a +convenience for people who want a way to \"just get a quick +REPL\" -- is actually implemented as just running the file named +in the customization variable `racket-repl-command-file'. By +default when that file doesn't exist, it is created to contain +just \"#lang racket/base\". You may edit the file to use a +different lang, require other modules, or whatever." (interactive "P") - (racket-call-racket-repl-buffer-name-function) - (racket--repl-ensure-buffer-and-session - nil - (lambda (repl-buffer) - (racket--repl-refresh-namespace-symbols) - (unless noselect - (select-window (get-buffer-window repl-buffer t)))))) + ;; Create file if it doesn't exist + (unless (file-exists-p racket-repl-command-file) + (let ((dir (file-name-directory racket-repl-command-file))) + (unless (file-exists-p dir) + (make-directory dir t))) + (write-region ";; Used by M-x racket-repl; you may edit\n#lang racket/base\n" + nil racket-repl-command-file)) + ;; Visit the file without selecting it, and run it. + (with-current-buffer (find-file-noselect racket-repl-command-file) + (let ((name (format "*Racket REPL <%s>*" racket-repl-command-file))) + (setq-local racket-repl-buffer-name name)) + (racket--repl-run + (list racket-repl-command-file) + nil + nil + (lambda () + (display-buffer racket-repl-buffer-name) + (unless noselect + (select-window (get-buffer-window racket-repl-buffer-name t))))))) ;;; Run